@strapi/content-type-builder 5.51.1 → 5.52.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.
Files changed (117) hide show
  1. package/dist/admin/components/AIChat/Chat.js +1 -1
  2. package/dist/admin/components/AIChat/Chat.js.map +1 -1
  3. package/dist/admin/components/AIChat/Chat.mjs +1 -1
  4. package/dist/admin/components/AIChat/Chat.mjs.map +1 -1
  5. package/dist/admin/components/AIChat/FeedbackModal.js +1 -1
  6. package/dist/admin/components/AIChat/FeedbackModal.js.map +1 -1
  7. package/dist/admin/components/AIChat/FeedbackModal.mjs +1 -1
  8. package/dist/admin/components/AIChat/FeedbackModal.mjs.map +1 -1
  9. package/dist/admin/components/AIChat/UploadFigmaModal.js +1 -1
  10. package/dist/admin/components/AIChat/UploadFigmaModal.js.map +1 -1
  11. package/dist/admin/components/AIChat/UploadFigmaModal.mjs +1 -1
  12. package/dist/admin/components/AIChat/UploadFigmaModal.mjs.map +1 -1
  13. package/dist/admin/components/AIChat/components/Base64Image.js +1 -1
  14. package/dist/admin/components/AIChat/components/Base64Image.js.map +1 -1
  15. package/dist/admin/components/AIChat/components/Base64Image.mjs +1 -1
  16. package/dist/admin/components/AIChat/components/Base64Image.mjs.map +1 -1
  17. package/dist/admin/components/AIChat/components/Messages/Message.js +2 -2
  18. package/dist/admin/components/AIChat/components/Messages/Message.js.map +1 -1
  19. package/dist/admin/components/AIChat/components/Messages/Message.mjs +2 -2
  20. package/dist/admin/components/AIChat/components/Messages/Message.mjs.map +1 -1
  21. package/dist/admin/components/AIChat/hooks/useAIFetch.js +1 -1
  22. package/dist/admin/components/AIChat/hooks/useAIFetch.js.map +1 -1
  23. package/dist/admin/components/AIChat/hooks/useAIFetch.mjs +1 -1
  24. package/dist/admin/components/AIChat/hooks/useAIFetch.mjs.map +1 -1
  25. package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.js +2 -2
  26. package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.js.map +1 -1
  27. package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.mjs +2 -2
  28. package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.mjs.map +1 -1
  29. package/dist/admin/components/CTBSession/useCTBTracking.js +1 -1
  30. package/dist/admin/components/CTBSession/useCTBTracking.js.map +1 -1
  31. package/dist/admin/components/CTBSession/useCTBTracking.mjs +1 -1
  32. package/dist/admin/components/CTBSession/useCTBTracking.mjs.map +1 -1
  33. package/dist/admin/components/DataManager/reducer.js +4 -0
  34. package/dist/admin/components/DataManager/reducer.js.map +1 -1
  35. package/dist/admin/components/DataManager/reducer.mjs +4 -0
  36. package/dist/admin/components/DataManager/reducer.mjs.map +1 -1
  37. package/dist/admin/components/DataManager/useServerRestartWatcher.js +1 -1
  38. package/dist/admin/components/DataManager/useServerRestartWatcher.js.map +1 -1
  39. package/dist/admin/components/DataManager/useServerRestartWatcher.mjs +1 -1
  40. package/dist/admin/components/DataManager/useServerRestartWatcher.mjs.map +1 -1
  41. package/dist/admin/components/FormModal/attributes/ConditionForm.js +1 -1
  42. package/dist/admin/components/FormModal/attributes/ConditionForm.js.map +1 -1
  43. package/dist/admin/components/FormModal/attributes/ConditionForm.mjs +1 -1
  44. package/dist/admin/components/FormModal/attributes/ConditionForm.mjs.map +1 -1
  45. package/dist/admin/components/FormModal/attributes/advancedForm.js +1 -0
  46. package/dist/admin/components/FormModal/attributes/advancedForm.js.map +1 -1
  47. package/dist/admin/components/FormModal/attributes/advancedForm.mjs +1 -0
  48. package/dist/admin/components/FormModal/attributes/advancedForm.mjs.map +1 -1
  49. package/dist/admin/components/FormModal/attributes/types.js +6 -1
  50. package/dist/admin/components/FormModal/attributes/types.js.map +1 -1
  51. package/dist/admin/components/FormModal/attributes/types.mjs +6 -1
  52. package/dist/admin/components/FormModal/attributes/types.mjs.map +1 -1
  53. package/dist/admin/components/FormModal/attributes/validation/common.js +6 -4
  54. package/dist/admin/components/FormModal/attributes/validation/common.js.map +1 -1
  55. package/dist/admin/components/FormModal/attributes/validation/common.mjs +6 -4
  56. package/dist/admin/components/FormModal/attributes/validation/common.mjs.map +1 -1
  57. package/dist/admin/components/FormModal/forms/forms.js +1 -1
  58. package/dist/admin/components/FormModal/forms/forms.js.map +1 -1
  59. package/dist/admin/components/FormModal/forms/forms.mjs +1 -1
  60. package/dist/admin/components/FormModal/forms/forms.mjs.map +1 -1
  61. package/dist/admin/components/FormModal/reducer.js +7 -0
  62. package/dist/admin/components/FormModal/reducer.js.map +1 -1
  63. package/dist/admin/components/FormModal/reducer.mjs +7 -0
  64. package/dist/admin/components/FormModal/reducer.mjs.map +1 -1
  65. package/dist/admin/components/PluralName.js +1 -1
  66. package/dist/admin/components/PluralName.js.map +1 -1
  67. package/dist/admin/components/PluralName.mjs +1 -1
  68. package/dist/admin/components/PluralName.mjs.map +1 -1
  69. package/dist/admin/src/components/CTBSession/useCTBTracking.d.ts +1 -1
  70. package/dist/admin/src/components/DataManager/utils/cleanData.d.ts +8 -0
  71. package/dist/admin/src/components/FormModal/attributes/types.d.ts +2 -0
  72. package/dist/admin/src/types.d.ts +1 -0
  73. package/dist/admin/translations/en.json.js +1 -0
  74. package/dist/admin/translations/en.json.js.map +1 -1
  75. package/dist/admin/translations/en.json.mjs +1 -0
  76. package/dist/admin/translations/en.json.mjs.map +1 -1
  77. package/dist/server/controllers/validation/common.js +1 -1
  78. package/dist/server/controllers/validation/common.js.map +1 -1
  79. package/dist/server/controllers/validation/common.mjs +1 -1
  80. package/dist/server/controllers/validation/common.mjs.map +1 -1
  81. package/dist/server/controllers/validation/relations.js +1 -0
  82. package/dist/server/controllers/validation/relations.js.map +1 -1
  83. package/dist/server/controllers/validation/relations.mjs +1 -0
  84. package/dist/server/controllers/validation/relations.mjs.map +1 -1
  85. package/dist/server/controllers/validation/schema.js +2 -1
  86. package/dist/server/controllers/validation/schema.js.map +1 -1
  87. package/dist/server/controllers/validation/schema.mjs +2 -1
  88. package/dist/server/controllers/validation/schema.mjs.map +1 -1
  89. package/dist/server/services/content-types.js +1 -1
  90. package/dist/server/services/content-types.js.map +1 -1
  91. package/dist/server/services/content-types.mjs +1 -1
  92. package/dist/server/services/content-types.mjs.map +1 -1
  93. package/dist/server/services/schema-builder/content-type-builder.js +3 -2
  94. package/dist/server/services/schema-builder/content-type-builder.js.map +1 -1
  95. package/dist/server/services/schema-builder/content-type-builder.mjs +3 -2
  96. package/dist/server/services/schema-builder/content-type-builder.mjs.map +1 -1
  97. package/dist/server/services/schema.js +1 -5
  98. package/dist/server/services/schema.js.map +1 -1
  99. package/dist/server/services/schema.mjs +2 -2
  100. package/dist/server/services/schema.mjs.map +1 -1
  101. package/dist/server/src/controllers/validation/relations.d.ts +2 -0
  102. package/dist/server/src/controllers/validation/relations.d.ts.map +1 -1
  103. package/dist/server/src/controllers/validation/schema.d.ts +3234 -0
  104. package/dist/server/src/controllers/validation/schema.d.ts.map +1 -1
  105. package/dist/server/src/services/schema-builder/types.d.ts +1 -0
  106. package/dist/server/src/services/schema-builder/types.d.ts.map +1 -1
  107. package/dist/server/src/utils/attributes.d.ts +10 -10
  108. package/dist/server/src/utils/attributes.d.ts.map +1 -1
  109. package/dist/server/utils/attributes.js +2 -2
  110. package/dist/server/utils/attributes.js.map +1 -1
  111. package/dist/server/utils/attributes.mjs +3 -2
  112. package/dist/server/utils/attributes.mjs.map +1 -1
  113. package/package.json +9 -9
  114. package/dist/server/src/controllers/ai/auth.d.ts +0 -1
  115. package/dist/server/src/controllers/ai/auth.d.ts.map +0 -1
  116. package/dist/server/src/controllers/ai/index.d.ts +0 -1
  117. package/dist/server/src/controllers/ai/index.d.ts.map +0 -1
@@ -39,7 +39,7 @@ const CHAT_TOO_LONG_ERROR = 'Chat too long';
39
39
  method: 'POST',
40
40
  headers: isJson ? {
41
41
  'Content-Type': 'application/json',
42
- ...options.headers || {}
42
+ ...options.headers
43
43
  } : options.headers,
44
44
  body: options.formData ? options.formData : isJson ? JSON.stringify(options.body || {}) : undefined,
45
45
  ctx: {
@@ -1 +1 @@
1
- {"version":3,"file":"useAIFetch.js","sources":["../../../../../admin/src/components/AIChat/hooks/useAIFetch.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\n\n/**\n * In charge of fetching data from Strapi AI endpoints\n */\n\nimport { useState } from 'react';\n\nimport { UIMessage, useChat } from '@ai-sdk/react';\nimport { useAppInfo } from '@strapi/admin/strapi-admin';\nimport { useGetAiUsageQuery } from '@strapi/admin/strapi-admin/ee';\nimport { DefaultChatTransport } from 'ai';\n\nimport { fetchAI, makeChatFetch, safeParseJson } from '../lib/aiClient';\nimport { STRAPI_AI_CHAT_URL, STRAPI_AI_URL } from '../lib/constants';\nimport { Attachment } from '../lib/types/attachments';\nimport { Schema } from '../lib/types/schema';\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n/**\n * Chat title\n */\nexport namespace GenerateTitle {\n export interface Request {\n body: {\n chatId: string;\n message: string;\n };\n }\n export interface Response {\n data: {\n title: string;\n };\n error?: string;\n }\n}\n\n/**\n * Upload a project to the chat\n */\nexport namespace UploadProject {\n export interface Request {\n body: {\n chatId: string;\n name: string;\n type: 'code';\n files: {\n path: string;\n content: string;\n }[];\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Send chat feedback\n */\nexport type FeedbackReasonIds =\n | 'invalid_schema'\n | 'bad_recommendation'\n | 'slow'\n | 'instructions_ignored'\n | 'being_lazy'\n | 'other';\n\nnamespace SendFeedback {\n export interface Request {\n body: {\n chatId: string;\n type: 'upvote' | 'downvote';\n feedback?: string;\n reasons?: FeedbackReasonIds[];\n messageId: string;\n messages: UIMessage[];\n schemas: Schema[];\n };\n }\n}\n\n/**\n * Upload media\n */\nexport namespace UploadMedia {\n export interface Request {\n body: {\n url: string; // base64 image\n filename: string;\n chatId: string;\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Collection of API endpoints and their corresponding request/response types\n */\ntype AIEndpoints = {\n '/schemas/chat/generate-title': {\n request: GenerateTitle.Request;\n response: GenerateTitle.Response;\n };\n '/schemas/chat/attachment': {\n request: UploadProject.Request;\n response: UploadProject.Response;\n };\n '/schemas/chat/feedback': {\n request: SendFeedback.Request;\n response: void;\n };\n '/media/upload': {\n request: UploadMedia.Request;\n response: UploadMedia.Response;\n };\n};\n\n// Helper type to extract the request type for a given endpoint\ntype RequestType<T extends keyof AIEndpoints> = AIEndpoints[T]['request'];\n\n// Helper type to extract the response type for a given endpoint\ntype ResponseType<T extends keyof AIEndpoints> = AIEndpoints[T]['response'];\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\nexport const TOO_MANY_REQUESTS_ERROR = 'Too many requests';\nexport const LICENSE_LIMIT_REACHED_ERROR = 'License limit';\nexport const LICENSE_LIMIT_EXCEEDED_ERROR = 'AI credit limit exceeded';\nexport const CHAT_TOO_LONG_ERROR = 'Chat too long';\nexport const ATTACHMENT_TOO_BIG_ERROR = 'Attachment too big';\nexport const ATTACHMENT_NOT_FOUND_ERROR = 'Attachment not found';\nexport const INVALID_REQUEST_ERROR = 'Invalid request';\n\n/**\n * Base hook factory for making type-safe API calls to Strapi AI endpoints.\n * Creates a hook specific to a single endpoint.\n */\nexport const createAIFetchHook = <T extends keyof AIEndpoints>(endpoint: T) => {\n return () => {\n const strapiVersion = useAppInfo('useAIFetch', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIFetch-user', (state) => state.userId);\n const aiUsage = useGetAiUsageQuery(undefined, { refetchOnMountOrArgChange: true });\n\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n /**\n * Make a type-safe API call to the specified Strapi AI endpoint with retry logic\n */\n const fetchData = async (\n options: Omit<RequestInit, 'body'> & Partial<RequestType<T>> & { formData?: FormData } = {}\n ): Promise<ResponseType<T> | null> => {\n setIsPending(true);\n setError(null);\n\n try {\n const fullUrl = `${STRAPI_AI_URL}${endpoint}`;\n const isJson = !!options.body && !options.formData;\n\n const response = await fetchAI(fullUrl, {\n method: 'POST',\n headers: isJson\n ? { 'Content-Type': 'application/json', ...(options.headers || {}) }\n : options.headers,\n body: options.formData\n ? options.formData\n : isJson\n ? JSON.stringify(options.body || {})\n : undefined,\n ctx: { strapiVersion, projectId, userId },\n });\n // refetch ai usage data on every successful request\n aiUsage.refetch();\n\n const body = await safeParseJson(response);\n\n if (!response.ok) {\n throw new Error(`Error: ${response.statusText}`);\n }\n return body as ResponseType<T>;\n } catch (err) {\n setError(err instanceof Error ? err.message : `Failed to fetch data from ${endpoint}`);\n return null;\n } finally {\n setIsPending(false);\n }\n };\n\n return {\n isPending,\n error,\n fetch: fetchData,\n };\n };\n};\n\n// Create specific hooks for each endpoint\nexport const useFetchGenerateTitle = createAIFetchHook('/schemas/chat/generate-title');\nexport const useFetchUploadProject = createAIFetchHook('/schemas/chat/attachment');\nexport const useFetchSendFeedback = createAIFetchHook('/schemas/chat/feedback');\nexport const useFetchUploadMedia = createAIFetchHook('/media/upload');\n\n/**\n * Hook wrapper for AI SDK's useChat with Strapi-specific configuration\n */\nexport const useAIChat: typeof useChat = (props) => {\n const strapiVersion = useAppInfo('useAIChat', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIChat-user', (state) => state.userId);\n\n const customFetch = makeChatFetch({ strapiVersion, projectId, userId });\n\n return useChat({\n ...props,\n transport: new DefaultChatTransport({\n api: STRAPI_AI_CHAT_URL,\n fetch: customFetch,\n }),\n });\n};\n"],"names":["TOO_MANY_REQUESTS_ERROR","LICENSE_LIMIT_REACHED_ERROR","LICENSE_LIMIT_EXCEEDED_ERROR","CHAT_TOO_LONG_ERROR","createAIFetchHook","endpoint","strapiVersion","useAppInfo","state","projectId","userId","aiUsage","useGetAiUsageQuery","undefined","refetchOnMountOrArgChange","isPending","setIsPending","useState","error","setError","fetchData","options","fullUrl","STRAPI_AI_URL","isJson","body","formData","response","fetchAI","method","headers","JSON","stringify","ctx","refetch","safeParseJson","ok","Error","statusText","err","message","fetch","useFetchGenerateTitle","useFetchUploadProject","useFetchSendFeedback","useFetchUploadMedia","useAIChat","props","customFetch","makeChatFetch","useChat","transport","DefaultChatTransport","api","STRAPI_AI_CHAT_URL"],"mappings":"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"}
1
+ {"version":3,"file":"useAIFetch.js","sources":["../../../../../admin/src/components/AIChat/hooks/useAIFetch.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\n\n/**\n * In charge of fetching data from Strapi AI endpoints\n */\n\nimport { useState } from 'react';\n\nimport { UIMessage, useChat } from '@ai-sdk/react';\nimport { useAppInfo } from '@strapi/admin/strapi-admin';\nimport { useGetAiUsageQuery } from '@strapi/admin/strapi-admin/ee';\nimport { DefaultChatTransport } from 'ai';\n\nimport { fetchAI, makeChatFetch, safeParseJson } from '../lib/aiClient';\nimport { STRAPI_AI_CHAT_URL, STRAPI_AI_URL } from '../lib/constants';\nimport { Attachment } from '../lib/types/attachments';\nimport { Schema } from '../lib/types/schema';\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n/**\n * Chat title\n */\nexport namespace GenerateTitle {\n export interface Request {\n body: {\n chatId: string;\n message: string;\n };\n }\n export interface Response {\n data: {\n title: string;\n };\n error?: string;\n }\n}\n\n/**\n * Upload a project to the chat\n */\nexport namespace UploadProject {\n export interface Request {\n body: {\n chatId: string;\n name: string;\n type: 'code';\n files: {\n path: string;\n content: string;\n }[];\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Send chat feedback\n */\nexport type FeedbackReasonIds =\n | 'invalid_schema'\n | 'bad_recommendation'\n | 'slow'\n | 'instructions_ignored'\n | 'being_lazy'\n | 'other';\n\nnamespace SendFeedback {\n export interface Request {\n body: {\n chatId: string;\n type: 'upvote' | 'downvote';\n feedback?: string;\n reasons?: FeedbackReasonIds[];\n messageId: string;\n messages: UIMessage[];\n schemas: Schema[];\n };\n }\n}\n\n/**\n * Upload media\n */\nexport namespace UploadMedia {\n export interface Request {\n body: {\n url: string; // base64 image\n filename: string;\n chatId: string;\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Collection of API endpoints and their corresponding request/response types\n */\ntype AIEndpoints = {\n '/schemas/chat/generate-title': {\n request: GenerateTitle.Request;\n response: GenerateTitle.Response;\n };\n '/schemas/chat/attachment': {\n request: UploadProject.Request;\n response: UploadProject.Response;\n };\n '/schemas/chat/feedback': {\n request: SendFeedback.Request;\n response: void;\n };\n '/media/upload': {\n request: UploadMedia.Request;\n response: UploadMedia.Response;\n };\n};\n\n// Helper type to extract the request type for a given endpoint\ntype RequestType<T extends keyof AIEndpoints> = AIEndpoints[T]['request'];\n\n// Helper type to extract the response type for a given endpoint\ntype ResponseType<T extends keyof AIEndpoints> = AIEndpoints[T]['response'];\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\nexport const TOO_MANY_REQUESTS_ERROR = 'Too many requests';\nexport const LICENSE_LIMIT_REACHED_ERROR = 'License limit';\nexport const LICENSE_LIMIT_EXCEEDED_ERROR = 'AI credit limit exceeded';\nexport const CHAT_TOO_LONG_ERROR = 'Chat too long';\nexport const ATTACHMENT_TOO_BIG_ERROR = 'Attachment too big';\nexport const ATTACHMENT_NOT_FOUND_ERROR = 'Attachment not found';\nexport const INVALID_REQUEST_ERROR = 'Invalid request';\n\n/**\n * Base hook factory for making type-safe API calls to Strapi AI endpoints.\n * Creates a hook specific to a single endpoint.\n */\nexport const createAIFetchHook = <T extends keyof AIEndpoints>(endpoint: T) => {\n return () => {\n const strapiVersion = useAppInfo('useAIFetch', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIFetch-user', (state) => state.userId);\n const aiUsage = useGetAiUsageQuery(undefined, { refetchOnMountOrArgChange: true });\n\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n /**\n * Make a type-safe API call to the specified Strapi AI endpoint with retry logic\n */\n const fetchData = async (\n options: Omit<RequestInit, 'body'> & Partial<RequestType<T>> & { formData?: FormData } = {}\n ): Promise<ResponseType<T> | null> => {\n setIsPending(true);\n setError(null);\n\n try {\n const fullUrl = `${STRAPI_AI_URL}${endpoint}`;\n const isJson = !!options.body && !options.formData;\n\n const response = await fetchAI(fullUrl, {\n method: 'POST',\n headers: isJson\n ? { 'Content-Type': 'application/json', ...options.headers }\n : options.headers,\n body: options.formData\n ? options.formData\n : isJson\n ? JSON.stringify(options.body || {})\n : undefined,\n ctx: { strapiVersion, projectId, userId },\n });\n // refetch ai usage data on every successful request\n aiUsage.refetch();\n\n const body = await safeParseJson(response);\n\n if (!response.ok) {\n throw new Error(`Error: ${response.statusText}`);\n }\n return body as ResponseType<T>;\n } catch (err) {\n setError(err instanceof Error ? err.message : `Failed to fetch data from ${endpoint}`);\n return null;\n } finally {\n setIsPending(false);\n }\n };\n\n return {\n isPending,\n error,\n fetch: fetchData,\n };\n };\n};\n\n// Create specific hooks for each endpoint\nexport const useFetchGenerateTitle = createAIFetchHook('/schemas/chat/generate-title');\nexport const useFetchUploadProject = createAIFetchHook('/schemas/chat/attachment');\nexport const useFetchSendFeedback = createAIFetchHook('/schemas/chat/feedback');\nexport const useFetchUploadMedia = createAIFetchHook('/media/upload');\n\n/**\n * Hook wrapper for AI SDK's useChat with Strapi-specific configuration\n */\nexport const useAIChat: typeof useChat = (props) => {\n const strapiVersion = useAppInfo('useAIChat', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIChat-user', (state) => state.userId);\n\n const customFetch = makeChatFetch({ strapiVersion, projectId, userId });\n\n return useChat({\n ...props,\n transport: new DefaultChatTransport({\n api: STRAPI_AI_CHAT_URL,\n fetch: customFetch,\n }),\n });\n};\n"],"names":["TOO_MANY_REQUESTS_ERROR","LICENSE_LIMIT_REACHED_ERROR","LICENSE_LIMIT_EXCEEDED_ERROR","CHAT_TOO_LONG_ERROR","createAIFetchHook","endpoint","strapiVersion","useAppInfo","state","projectId","userId","aiUsage","useGetAiUsageQuery","undefined","refetchOnMountOrArgChange","isPending","setIsPending","useState","error","setError","fetchData","options","fullUrl","STRAPI_AI_URL","isJson","body","formData","response","fetchAI","method","headers","JSON","stringify","ctx","refetch","safeParseJson","ok","Error","statusText","err","message","fetch","useFetchGenerateTitle","useFetchUploadProject","useFetchSendFeedback","useFetchUploadMedia","useAIChat","props","customFetch","makeChatFetch","useChat","transport","DefaultChatTransport","api","STRAPI_AI_CHAT_URL"],"mappings":"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"}
@@ -37,7 +37,7 @@ const CHAT_TOO_LONG_ERROR = 'Chat too long';
37
37
  method: 'POST',
38
38
  headers: isJson ? {
39
39
  'Content-Type': 'application/json',
40
- ...options.headers || {}
40
+ ...options.headers
41
41
  } : options.headers,
42
42
  body: options.formData ? options.formData : isJson ? JSON.stringify(options.body || {}) : undefined,
43
43
  ctx: {
@@ -1 +1 @@
1
- {"version":3,"file":"useAIFetch.mjs","sources":["../../../../../admin/src/components/AIChat/hooks/useAIFetch.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\n\n/**\n * In charge of fetching data from Strapi AI endpoints\n */\n\nimport { useState } from 'react';\n\nimport { UIMessage, useChat } from '@ai-sdk/react';\nimport { useAppInfo } from '@strapi/admin/strapi-admin';\nimport { useGetAiUsageQuery } from '@strapi/admin/strapi-admin/ee';\nimport { DefaultChatTransport } from 'ai';\n\nimport { fetchAI, makeChatFetch, safeParseJson } from '../lib/aiClient';\nimport { STRAPI_AI_CHAT_URL, STRAPI_AI_URL } from '../lib/constants';\nimport { Attachment } from '../lib/types/attachments';\nimport { Schema } from '../lib/types/schema';\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n/**\n * Chat title\n */\nexport namespace GenerateTitle {\n export interface Request {\n body: {\n chatId: string;\n message: string;\n };\n }\n export interface Response {\n data: {\n title: string;\n };\n error?: string;\n }\n}\n\n/**\n * Upload a project to the chat\n */\nexport namespace UploadProject {\n export interface Request {\n body: {\n chatId: string;\n name: string;\n type: 'code';\n files: {\n path: string;\n content: string;\n }[];\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Send chat feedback\n */\nexport type FeedbackReasonIds =\n | 'invalid_schema'\n | 'bad_recommendation'\n | 'slow'\n | 'instructions_ignored'\n | 'being_lazy'\n | 'other';\n\nnamespace SendFeedback {\n export interface Request {\n body: {\n chatId: string;\n type: 'upvote' | 'downvote';\n feedback?: string;\n reasons?: FeedbackReasonIds[];\n messageId: string;\n messages: UIMessage[];\n schemas: Schema[];\n };\n }\n}\n\n/**\n * Upload media\n */\nexport namespace UploadMedia {\n export interface Request {\n body: {\n url: string; // base64 image\n filename: string;\n chatId: string;\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Collection of API endpoints and their corresponding request/response types\n */\ntype AIEndpoints = {\n '/schemas/chat/generate-title': {\n request: GenerateTitle.Request;\n response: GenerateTitle.Response;\n };\n '/schemas/chat/attachment': {\n request: UploadProject.Request;\n response: UploadProject.Response;\n };\n '/schemas/chat/feedback': {\n request: SendFeedback.Request;\n response: void;\n };\n '/media/upload': {\n request: UploadMedia.Request;\n response: UploadMedia.Response;\n };\n};\n\n// Helper type to extract the request type for a given endpoint\ntype RequestType<T extends keyof AIEndpoints> = AIEndpoints[T]['request'];\n\n// Helper type to extract the response type for a given endpoint\ntype ResponseType<T extends keyof AIEndpoints> = AIEndpoints[T]['response'];\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\nexport const TOO_MANY_REQUESTS_ERROR = 'Too many requests';\nexport const LICENSE_LIMIT_REACHED_ERROR = 'License limit';\nexport const LICENSE_LIMIT_EXCEEDED_ERROR = 'AI credit limit exceeded';\nexport const CHAT_TOO_LONG_ERROR = 'Chat too long';\nexport const ATTACHMENT_TOO_BIG_ERROR = 'Attachment too big';\nexport const ATTACHMENT_NOT_FOUND_ERROR = 'Attachment not found';\nexport const INVALID_REQUEST_ERROR = 'Invalid request';\n\n/**\n * Base hook factory for making type-safe API calls to Strapi AI endpoints.\n * Creates a hook specific to a single endpoint.\n */\nexport const createAIFetchHook = <T extends keyof AIEndpoints>(endpoint: T) => {\n return () => {\n const strapiVersion = useAppInfo('useAIFetch', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIFetch-user', (state) => state.userId);\n const aiUsage = useGetAiUsageQuery(undefined, { refetchOnMountOrArgChange: true });\n\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n /**\n * Make a type-safe API call to the specified Strapi AI endpoint with retry logic\n */\n const fetchData = async (\n options: Omit<RequestInit, 'body'> & Partial<RequestType<T>> & { formData?: FormData } = {}\n ): Promise<ResponseType<T> | null> => {\n setIsPending(true);\n setError(null);\n\n try {\n const fullUrl = `${STRAPI_AI_URL}${endpoint}`;\n const isJson = !!options.body && !options.formData;\n\n const response = await fetchAI(fullUrl, {\n method: 'POST',\n headers: isJson\n ? { 'Content-Type': 'application/json', ...(options.headers || {}) }\n : options.headers,\n body: options.formData\n ? options.formData\n : isJson\n ? JSON.stringify(options.body || {})\n : undefined,\n ctx: { strapiVersion, projectId, userId },\n });\n // refetch ai usage data on every successful request\n aiUsage.refetch();\n\n const body = await safeParseJson(response);\n\n if (!response.ok) {\n throw new Error(`Error: ${response.statusText}`);\n }\n return body as ResponseType<T>;\n } catch (err) {\n setError(err instanceof Error ? err.message : `Failed to fetch data from ${endpoint}`);\n return null;\n } finally {\n setIsPending(false);\n }\n };\n\n return {\n isPending,\n error,\n fetch: fetchData,\n };\n };\n};\n\n// Create specific hooks for each endpoint\nexport const useFetchGenerateTitle = createAIFetchHook('/schemas/chat/generate-title');\nexport const useFetchUploadProject = createAIFetchHook('/schemas/chat/attachment');\nexport const useFetchSendFeedback = createAIFetchHook('/schemas/chat/feedback');\nexport const useFetchUploadMedia = createAIFetchHook('/media/upload');\n\n/**\n * Hook wrapper for AI SDK's useChat with Strapi-specific configuration\n */\nexport const useAIChat: typeof useChat = (props) => {\n const strapiVersion = useAppInfo('useAIChat', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIChat-user', (state) => state.userId);\n\n const customFetch = makeChatFetch({ strapiVersion, projectId, userId });\n\n return useChat({\n ...props,\n transport: new DefaultChatTransport({\n api: STRAPI_AI_CHAT_URL,\n fetch: customFetch,\n }),\n });\n};\n"],"names":["TOO_MANY_REQUESTS_ERROR","LICENSE_LIMIT_REACHED_ERROR","LICENSE_LIMIT_EXCEEDED_ERROR","CHAT_TOO_LONG_ERROR","createAIFetchHook","endpoint","strapiVersion","useAppInfo","state","projectId","userId","aiUsage","useGetAiUsageQuery","undefined","refetchOnMountOrArgChange","isPending","setIsPending","useState","error","setError","fetchData","options","fullUrl","STRAPI_AI_URL","isJson","body","formData","response","fetchAI","method","headers","JSON","stringify","ctx","refetch","safeParseJson","ok","Error","statusText","err","message","fetch","useFetchGenerateTitle","useFetchUploadProject","useFetchSendFeedback","useFetchUploadMedia","useAIChat","props","customFetch","makeChatFetch","useChat","transport","DefaultChatTransport","api","STRAPI_AI_CHAT_URL"],"mappings":"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"}
1
+ {"version":3,"file":"useAIFetch.mjs","sources":["../../../../../admin/src/components/AIChat/hooks/useAIFetch.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\n\n/**\n * In charge of fetching data from Strapi AI endpoints\n */\n\nimport { useState } from 'react';\n\nimport { UIMessage, useChat } from '@ai-sdk/react';\nimport { useAppInfo } from '@strapi/admin/strapi-admin';\nimport { useGetAiUsageQuery } from '@strapi/admin/strapi-admin/ee';\nimport { DefaultChatTransport } from 'ai';\n\nimport { fetchAI, makeChatFetch, safeParseJson } from '../lib/aiClient';\nimport { STRAPI_AI_CHAT_URL, STRAPI_AI_URL } from '../lib/constants';\nimport { Attachment } from '../lib/types/attachments';\nimport { Schema } from '../lib/types/schema';\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n/**\n * Chat title\n */\nexport namespace GenerateTitle {\n export interface Request {\n body: {\n chatId: string;\n message: string;\n };\n }\n export interface Response {\n data: {\n title: string;\n };\n error?: string;\n }\n}\n\n/**\n * Upload a project to the chat\n */\nexport namespace UploadProject {\n export interface Request {\n body: {\n chatId: string;\n name: string;\n type: 'code';\n files: {\n path: string;\n content: string;\n }[];\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Send chat feedback\n */\nexport type FeedbackReasonIds =\n | 'invalid_schema'\n | 'bad_recommendation'\n | 'slow'\n | 'instructions_ignored'\n | 'being_lazy'\n | 'other';\n\nnamespace SendFeedback {\n export interface Request {\n body: {\n chatId: string;\n type: 'upvote' | 'downvote';\n feedback?: string;\n reasons?: FeedbackReasonIds[];\n messageId: string;\n messages: UIMessage[];\n schemas: Schema[];\n };\n }\n}\n\n/**\n * Upload media\n */\nexport namespace UploadMedia {\n export interface Request {\n body: {\n url: string; // base64 image\n filename: string;\n chatId: string;\n };\n }\n export interface Response {\n data: Attachment;\n error?: string;\n }\n}\n\n/**\n * Collection of API endpoints and their corresponding request/response types\n */\ntype AIEndpoints = {\n '/schemas/chat/generate-title': {\n request: GenerateTitle.Request;\n response: GenerateTitle.Response;\n };\n '/schemas/chat/attachment': {\n request: UploadProject.Request;\n response: UploadProject.Response;\n };\n '/schemas/chat/feedback': {\n request: SendFeedback.Request;\n response: void;\n };\n '/media/upload': {\n request: UploadMedia.Request;\n response: UploadMedia.Response;\n };\n};\n\n// Helper type to extract the request type for a given endpoint\ntype RequestType<T extends keyof AIEndpoints> = AIEndpoints[T]['request'];\n\n// Helper type to extract the response type for a given endpoint\ntype ResponseType<T extends keyof AIEndpoints> = AIEndpoints[T]['response'];\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\nexport const TOO_MANY_REQUESTS_ERROR = 'Too many requests';\nexport const LICENSE_LIMIT_REACHED_ERROR = 'License limit';\nexport const LICENSE_LIMIT_EXCEEDED_ERROR = 'AI credit limit exceeded';\nexport const CHAT_TOO_LONG_ERROR = 'Chat too long';\nexport const ATTACHMENT_TOO_BIG_ERROR = 'Attachment too big';\nexport const ATTACHMENT_NOT_FOUND_ERROR = 'Attachment not found';\nexport const INVALID_REQUEST_ERROR = 'Invalid request';\n\n/**\n * Base hook factory for making type-safe API calls to Strapi AI endpoints.\n * Creates a hook specific to a single endpoint.\n */\nexport const createAIFetchHook = <T extends keyof AIEndpoints>(endpoint: T) => {\n return () => {\n const strapiVersion = useAppInfo('useAIFetch', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIFetch-user', (state) => state.userId);\n const aiUsage = useGetAiUsageQuery(undefined, { refetchOnMountOrArgChange: true });\n\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n /**\n * Make a type-safe API call to the specified Strapi AI endpoint with retry logic\n */\n const fetchData = async (\n options: Omit<RequestInit, 'body'> & Partial<RequestType<T>> & { formData?: FormData } = {}\n ): Promise<ResponseType<T> | null> => {\n setIsPending(true);\n setError(null);\n\n try {\n const fullUrl = `${STRAPI_AI_URL}${endpoint}`;\n const isJson = !!options.body && !options.formData;\n\n const response = await fetchAI(fullUrl, {\n method: 'POST',\n headers: isJson\n ? { 'Content-Type': 'application/json', ...options.headers }\n : options.headers,\n body: options.formData\n ? options.formData\n : isJson\n ? JSON.stringify(options.body || {})\n : undefined,\n ctx: { strapiVersion, projectId, userId },\n });\n // refetch ai usage data on every successful request\n aiUsage.refetch();\n\n const body = await safeParseJson(response);\n\n if (!response.ok) {\n throw new Error(`Error: ${response.statusText}`);\n }\n return body as ResponseType<T>;\n } catch (err) {\n setError(err instanceof Error ? err.message : `Failed to fetch data from ${endpoint}`);\n return null;\n } finally {\n setIsPending(false);\n }\n };\n\n return {\n isPending,\n error,\n fetch: fetchData,\n };\n };\n};\n\n// Create specific hooks for each endpoint\nexport const useFetchGenerateTitle = createAIFetchHook('/schemas/chat/generate-title');\nexport const useFetchUploadProject = createAIFetchHook('/schemas/chat/attachment');\nexport const useFetchSendFeedback = createAIFetchHook('/schemas/chat/feedback');\nexport const useFetchUploadMedia = createAIFetchHook('/media/upload');\n\n/**\n * Hook wrapper for AI SDK's useChat with Strapi-specific configuration\n */\nexport const useAIChat: typeof useChat = (props) => {\n const strapiVersion = useAppInfo('useAIChat', (state) => state.strapiVersion);\n const projectId = useAppInfo('useAIFetch', (state) => state.projectId);\n const userId = useAppInfo('useAIChat-user', (state) => state.userId);\n\n const customFetch = makeChatFetch({ strapiVersion, projectId, userId });\n\n return useChat({\n ...props,\n transport: new DefaultChatTransport({\n api: STRAPI_AI_CHAT_URL,\n fetch: customFetch,\n }),\n });\n};\n"],"names":["TOO_MANY_REQUESTS_ERROR","LICENSE_LIMIT_REACHED_ERROR","LICENSE_LIMIT_EXCEEDED_ERROR","CHAT_TOO_LONG_ERROR","createAIFetchHook","endpoint","strapiVersion","useAppInfo","state","projectId","userId","aiUsage","useGetAiUsageQuery","undefined","refetchOnMountOrArgChange","isPending","setIsPending","useState","error","setError","fetchData","options","fullUrl","STRAPI_AI_URL","isJson","body","formData","response","fetchAI","method","headers","JSON","stringify","ctx","refetch","safeParseJson","ok","Error","statusText","err","message","fetch","useFetchGenerateTitle","useFetchUploadProject","useFetchSendFeedback","useFetchUploadMedia","useAIChat","props","customFetch","makeChatFetch","useChat","transport","DefaultChatTransport","api","STRAPI_AI_CHAT_URL"],"mappings":"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"}
@@ -188,8 +188,8 @@ const ACTION_TO_STATUS = {
188
188
  ...prev.pluginOptions,
189
189
  ...contentTypeBase.pluginOptions,
190
190
  i18n: {
191
- ...prev.pluginOptions?.i18n ?? {},
192
- ...contentTypeBase.pluginOptions?.i18n ?? {},
191
+ ...prev.pluginOptions?.i18n,
192
+ ...contentTypeBase.pluginOptions?.i18n,
193
193
  localized: schema.options?.localized ?? prev.pluginOptions?.i18n?.localized ?? false
194
194
  }
195
195
  },
@@ -1 +1 @@
1
- {"version":3,"file":"toCTB.js","sources":["../../../../../../../admin/src/components/AIChat/lib/transforms/schemas/toCTB.ts"],"sourcesContent":["import isEqual from 'lodash/isEqual';\nimport omit from 'lodash/omit';\nimport pluralize from 'pluralize';\n\nimport type { ContentType, Component, AnyAttribute } from '../../../../../types';\nimport type { Schema, SchemaAttribute } from '../../types/schema';\nimport type { Struct, UID } from '@strapi/types';\n\nconst isPluginContentTypeUid = (uid: string) => uid.startsWith('plugin::');\n\nconst isContentTypeKind = (kind: Schema['kind']): kind is Struct.ContentTypeKind => {\n return kind === 'collectionType' || kind === 'singleType';\n};\n\n/**\n * Plugin / extension content-types use server-derived identity (globalId, collectionName, …).\n * The AI chat uses a simplified shape that would otherwise overwrite those fields incorrectly.\n */\nconst isPluginContentType = (schema: Schema, oldSchema?: ContentType | Component): boolean => {\n if (schema.plugin || isPluginContentTypeUid(schema.uid)) {\n return true;\n }\n if (oldSchema && 'modelType' in oldSchema && oldSchema.modelType === 'contentType') {\n const ct = oldSchema as ContentType;\n return Boolean(ct.plugin) || isPluginContentTypeUid(String(ct.uid));\n }\n return false;\n};\n\nconst ACTION_TO_STATUS: Record<Schema['action'], ContentType['status']> = {\n create: 'NEW',\n remove: 'REMOVED',\n update: 'CHANGED',\n};\n\n/**\n * Creates a new attribute with the specified status\n */\nconst createAttributeWithStatus = (\n name: string,\n attributeData: SchemaAttribute | AnyAttribute,\n status: AnyAttribute['status']\n): AnyAttribute =>\n ({\n ...attributeData,\n name,\n status,\n }) as AnyAttribute;\n\n/**\n * Determines the status of an attribute by comparing new and old versions\n */\nconst determineAttributeStatus = (\n newAttr: Record<string, unknown>,\n oldAttr?: AnyAttribute,\n oldSchema?: ContentType | Component\n): AnyAttribute['status'] => {\n if (!oldAttr) {\n return 'NEW';\n }\n\n // If the schema was already new, don't mark attributes as changed, keep them as new.\n if (oldSchema?.status === 'NEW') {\n return 'NEW';\n }\n\n // Compare attributes without the status field to determine if they've changed\n const newAttrWithoutStatus = omit(newAttr, ['status']);\n const oldAttrWithoutStatus = omit(oldAttr, ['status']);\n\n if (!isEqual(newAttrWithoutStatus, oldAttrWithoutStatus)) {\n return 'CHANGED';\n }\n\n // If unchanged, keep the previous status\n return oldAttr.status;\n};\n\n/**\n * Determines the status of a schema by comparing action and checking if oldSchema exists\n */\nconst transformStatusFromChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType['status'] => {\n // If schema has an action, use the mapped status\n if (schema.action) {\n return ACTION_TO_STATUS[schema.action];\n }\n\n // If oldSchema doesn't exist, it's a new schema\n if (!oldSchema) {\n return 'NEW';\n }\n\n // If no action is specified and oldSchema exists, keep the existing status\n return oldSchema.status;\n};\n\n/**\n * Transform attributes from Chat format to CTB format\n * Also performs a diff to determine the status of each attribute\n */\nexport const transformAttributesFromChatToCTB = (\n { action, attributes }: Schema,\n oldSchema?: ContentType | Component\n): AnyAttribute[] => {\n // If it's a new schema or no oldAttributes provided, all attributes are NEW\n if (action === 'create' || !oldSchema) {\n return Object.entries(attributes).map(([name, attribute]) =>\n createAttributeWithStatus(name, attribute, 'NEW')\n );\n }\n\n // Convert old attributes array to a lookup map for faster access\n const oldAttributesMap = oldSchema.attributes.reduce(\n (acc, attr) => ({ ...acc, [attr.name]: attr }),\n {} as Record<string, AnyAttribute>\n );\n\n // Process current attributes (new and changed)\n const processedAttributes = Object.entries(attributes).map(([name, attr]) => {\n const oldAttr = oldAttributesMap[name];\n const status = determineAttributeStatus({ ...attr, name }, oldAttr, oldSchema);\n\n return createAttributeWithStatus(name, attr, status);\n });\n\n // No need to mark removed attributes if the old schema is new, just remove it from the list\n // TODO: Else a validation error occurs on the backend side.\n if (oldSchema?.status === 'NEW') {\n return processedAttributes;\n }\n\n // Find removed attributes (exist in old but not in new)\n const removedAttributes = Object.entries(oldAttributesMap)\n .filter(([name]) => !attributes[name])\n .map(([name, oldAttr]) => createAttributeWithStatus(name, oldAttr, 'REMOVED'));\n\n // Combine both sets of attributes\n return [...processedAttributes, ...removedAttributes];\n};\n\n/**\n * Transform schema format\n * AI chat -> CTB\n *\n * The AI chat returns a simplified format, and this layer transforms it to be compatible with the CTB reducer.\n *\n * We need to keep track of which changes have been made\n */\nexport const transformChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType | Component => {\n const singularName = pluralize.singular(schema.name).toLowerCase().replace(/ /g, '-');\n const pluralName = pluralize.plural(schema.name).toLowerCase().replace(/ /g, '-');\n\n if (schema.modelType === 'component') {\n return {\n category: schema.category || 'default',\n modelName: singularName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n info: {\n displayName: schema.name,\n description: schema.description,\n // TODO\n // icon: schema.icon,\n },\n modelType: schema.modelType,\n uid: schema.uid as UID.Component,\n collectionName: pluralName,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n } satisfies Component;\n }\n\n const previousContentType = oldSchema?.modelType === 'contentType' ? oldSchema : undefined;\n const kind = isContentTypeKind(schema.kind) ? schema.kind : 'collectionType';\n\n const contentTypeBase = {\n uid: schema.uid as UID.ContentType,\n modelType: 'contentType',\n modelName: singularName,\n kind,\n info: {\n displayName: schema.name.charAt(0).toUpperCase() + schema.name.slice(1),\n // Always keep the old by default\n singularName: previousContentType?.info.singularName ?? singularName,\n // Always keep the old by default\n pluralName: previousContentType?.info.pluralName ?? pluralName,\n },\n collectionName: pluralName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n options: {\n draftAndPublish: schema.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n i18n: {\n localized: schema.options?.localized ?? false,\n },\n },\n visible: true,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n restrictRelationsTo: null, // TODO: not sure what this is about\n } satisfies ContentType;\n\n if (\n isPluginContentType(schema, oldSchema) &&\n oldSchema &&\n oldSchema.modelType === 'contentType'\n ) {\n const prev = oldSchema as ContentType;\n return {\n ...contentTypeBase,\n plugin: prev.plugin ?? schema.plugin,\n globalId: prev.globalId,\n modelName: prev.modelName,\n collectionName: prev.collectionName,\n info: {\n ...contentTypeBase.info,\n singularName: prev.info.singularName,\n pluralName: prev.info.pluralName,\n },\n options: {\n ...prev.options,\n ...contentTypeBase.options,\n draftAndPublish: schema.options?.draftAndPublish ?? prev.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n ...prev.pluginOptions,\n ...contentTypeBase.pluginOptions,\n i18n: {\n ...((prev.pluginOptions?.i18n as Record<string, unknown> | undefined) ?? {}),\n ...((contentTypeBase.pluginOptions?.i18n as Record<string, unknown> | undefined) ?? {}),\n localized:\n schema.options?.localized ??\n (prev.pluginOptions?.i18n as { localized?: boolean } | undefined)?.localized ??\n false,\n },\n },\n visible: prev.visible,\n restrictRelationsTo: prev.restrictRelationsTo,\n } satisfies ContentType;\n }\n\n if (isPluginContentType(schema, oldSchema) && schema.plugin) {\n return {\n ...contentTypeBase,\n plugin: schema.plugin,\n } satisfies ContentType;\n }\n\n return contentTypeBase;\n};\n"],"names":["isPluginContentTypeUid","uid","startsWith","isContentTypeKind","kind","isPluginContentType","schema","oldSchema","plugin","modelType","ct","Boolean","String","ACTION_TO_STATUS","create","remove","update","createAttributeWithStatus","name","attributeData","status","determineAttributeStatus","newAttr","oldAttr","newAttrWithoutStatus","omit","oldAttrWithoutStatus","isEqual","transformStatusFromChatToCTB","action","transformAttributesFromChatToCTB","attributes","Object","entries","map","attribute","oldAttributesMap","reduce","acc","attr","processedAttributes","removedAttributes","filter","transformChatToCTB","singularName","pluralize","singular","toLowerCase","replace","pluralName","plural","category","modelName","info","displayName","description","collectionName","globalId","previousContentType","undefined","contentTypeBase","charAt","toUpperCase","slice","options","draftAndPublish","pluginOptions","i18n","localized","visible","restrictRelationsTo","prev"],"mappings":"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"}
1
+ {"version":3,"file":"toCTB.js","sources":["../../../../../../../admin/src/components/AIChat/lib/transforms/schemas/toCTB.ts"],"sourcesContent":["import isEqual from 'lodash/isEqual';\nimport omit from 'lodash/omit';\nimport pluralize from 'pluralize';\n\nimport type { ContentType, Component, AnyAttribute } from '../../../../../types';\nimport type { Schema, SchemaAttribute } from '../../types/schema';\nimport type { Struct, UID } from '@strapi/types';\n\nconst isPluginContentTypeUid = (uid: string) => uid.startsWith('plugin::');\n\nconst isContentTypeKind = (kind: Schema['kind']): kind is Struct.ContentTypeKind => {\n return kind === 'collectionType' || kind === 'singleType';\n};\n\n/**\n * Plugin / extension content-types use server-derived identity (globalId, collectionName, …).\n * The AI chat uses a simplified shape that would otherwise overwrite those fields incorrectly.\n */\nconst isPluginContentType = (schema: Schema, oldSchema?: ContentType | Component): boolean => {\n if (schema.plugin || isPluginContentTypeUid(schema.uid)) {\n return true;\n }\n if (oldSchema && 'modelType' in oldSchema && oldSchema.modelType === 'contentType') {\n const ct = oldSchema as ContentType;\n return Boolean(ct.plugin) || isPluginContentTypeUid(String(ct.uid));\n }\n return false;\n};\n\nconst ACTION_TO_STATUS: Record<Schema['action'], ContentType['status']> = {\n create: 'NEW',\n remove: 'REMOVED',\n update: 'CHANGED',\n};\n\n/**\n * Creates a new attribute with the specified status\n */\nconst createAttributeWithStatus = (\n name: string,\n attributeData: SchemaAttribute | AnyAttribute,\n status: AnyAttribute['status']\n): AnyAttribute =>\n ({\n ...attributeData,\n name,\n status,\n }) as AnyAttribute;\n\n/**\n * Determines the status of an attribute by comparing new and old versions\n */\nconst determineAttributeStatus = (\n newAttr: Record<string, unknown>,\n oldAttr?: AnyAttribute,\n oldSchema?: ContentType | Component\n): AnyAttribute['status'] => {\n if (!oldAttr) {\n return 'NEW';\n }\n\n // If the schema was already new, don't mark attributes as changed, keep them as new.\n if (oldSchema?.status === 'NEW') {\n return 'NEW';\n }\n\n // Compare attributes without the status field to determine if they've changed\n const newAttrWithoutStatus = omit(newAttr, ['status']);\n const oldAttrWithoutStatus = omit(oldAttr, ['status']);\n\n if (!isEqual(newAttrWithoutStatus, oldAttrWithoutStatus)) {\n return 'CHANGED';\n }\n\n // If unchanged, keep the previous status\n return oldAttr.status;\n};\n\n/**\n * Determines the status of a schema by comparing action and checking if oldSchema exists\n */\nconst transformStatusFromChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType['status'] => {\n // If schema has an action, use the mapped status\n if (schema.action) {\n return ACTION_TO_STATUS[schema.action];\n }\n\n // If oldSchema doesn't exist, it's a new schema\n if (!oldSchema) {\n return 'NEW';\n }\n\n // If no action is specified and oldSchema exists, keep the existing status\n return oldSchema.status;\n};\n\n/**\n * Transform attributes from Chat format to CTB format\n * Also performs a diff to determine the status of each attribute\n */\nexport const transformAttributesFromChatToCTB = (\n { action, attributes }: Schema,\n oldSchema?: ContentType | Component\n): AnyAttribute[] => {\n // If it's a new schema or no oldAttributes provided, all attributes are NEW\n if (action === 'create' || !oldSchema) {\n return Object.entries(attributes).map(([name, attribute]) =>\n createAttributeWithStatus(name, attribute, 'NEW')\n );\n }\n\n // Convert old attributes array to a lookup map for faster access\n const oldAttributesMap = oldSchema.attributes.reduce(\n (acc, attr) => ({ ...acc, [attr.name]: attr }),\n {} as Record<string, AnyAttribute>\n );\n\n // Process current attributes (new and changed)\n const processedAttributes = Object.entries(attributes).map(([name, attr]) => {\n const oldAttr = oldAttributesMap[name];\n const status = determineAttributeStatus({ ...attr, name }, oldAttr, oldSchema);\n\n return createAttributeWithStatus(name, attr, status);\n });\n\n // No need to mark removed attributes if the old schema is new, just remove it from the list\n // TODO: Else a validation error occurs on the backend side.\n if (oldSchema?.status === 'NEW') {\n return processedAttributes;\n }\n\n // Find removed attributes (exist in old but not in new)\n const removedAttributes = Object.entries(oldAttributesMap)\n .filter(([name]) => !attributes[name])\n .map(([name, oldAttr]) => createAttributeWithStatus(name, oldAttr, 'REMOVED'));\n\n // Combine both sets of attributes\n return [...processedAttributes, ...removedAttributes];\n};\n\n/**\n * Transform schema format\n * AI chat -> CTB\n *\n * The AI chat returns a simplified format, and this layer transforms it to be compatible with the CTB reducer.\n *\n * We need to keep track of which changes have been made\n */\nexport const transformChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType | Component => {\n const singularName = pluralize.singular(schema.name).toLowerCase().replace(/ /g, '-');\n const pluralName = pluralize.plural(schema.name).toLowerCase().replace(/ /g, '-');\n\n if (schema.modelType === 'component') {\n return {\n category: schema.category || 'default',\n modelName: singularName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n info: {\n displayName: schema.name,\n description: schema.description,\n // TODO\n // icon: schema.icon,\n },\n modelType: schema.modelType,\n uid: schema.uid as UID.Component,\n collectionName: pluralName,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n } satisfies Component;\n }\n\n const previousContentType = oldSchema?.modelType === 'contentType' ? oldSchema : undefined;\n const kind = isContentTypeKind(schema.kind) ? schema.kind : 'collectionType';\n\n const contentTypeBase = {\n uid: schema.uid as UID.ContentType,\n modelType: 'contentType',\n modelName: singularName,\n kind,\n info: {\n displayName: schema.name.charAt(0).toUpperCase() + schema.name.slice(1),\n // Always keep the old by default\n singularName: previousContentType?.info.singularName ?? singularName,\n // Always keep the old by default\n pluralName: previousContentType?.info.pluralName ?? pluralName,\n },\n collectionName: pluralName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n options: {\n draftAndPublish: schema.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n i18n: {\n localized: schema.options?.localized ?? false,\n },\n },\n visible: true,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n restrictRelationsTo: null, // TODO: not sure what this is about\n } satisfies ContentType;\n\n if (\n isPluginContentType(schema, oldSchema) &&\n oldSchema &&\n oldSchema.modelType === 'contentType'\n ) {\n const prev = oldSchema as ContentType;\n return {\n ...contentTypeBase,\n plugin: prev.plugin ?? schema.plugin,\n globalId: prev.globalId,\n modelName: prev.modelName,\n collectionName: prev.collectionName,\n info: {\n ...contentTypeBase.info,\n singularName: prev.info.singularName,\n pluralName: prev.info.pluralName,\n },\n options: {\n ...prev.options,\n ...contentTypeBase.options,\n draftAndPublish: schema.options?.draftAndPublish ?? prev.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n ...prev.pluginOptions,\n ...contentTypeBase.pluginOptions,\n i18n: {\n ...(prev.pluginOptions?.i18n as Record<string, unknown> | undefined),\n ...(contentTypeBase.pluginOptions?.i18n as Record<string, unknown> | undefined),\n localized:\n schema.options?.localized ??\n (prev.pluginOptions?.i18n as { localized?: boolean } | undefined)?.localized ??\n false,\n },\n },\n visible: prev.visible,\n restrictRelationsTo: prev.restrictRelationsTo,\n } satisfies ContentType;\n }\n\n if (isPluginContentType(schema, oldSchema) && schema.plugin) {\n return {\n ...contentTypeBase,\n plugin: schema.plugin,\n } satisfies ContentType;\n }\n\n return contentTypeBase;\n};\n"],"names":["isPluginContentTypeUid","uid","startsWith","isContentTypeKind","kind","isPluginContentType","schema","oldSchema","plugin","modelType","ct","Boolean","String","ACTION_TO_STATUS","create","remove","update","createAttributeWithStatus","name","attributeData","status","determineAttributeStatus","newAttr","oldAttr","newAttrWithoutStatus","omit","oldAttrWithoutStatus","isEqual","transformStatusFromChatToCTB","action","transformAttributesFromChatToCTB","attributes","Object","entries","map","attribute","oldAttributesMap","reduce","acc","attr","processedAttributes","removedAttributes","filter","transformChatToCTB","singularName","pluralize","singular","toLowerCase","replace","pluralName","plural","category","modelName","info","displayName","description","collectionName","globalId","previousContentType","undefined","contentTypeBase","charAt","toUpperCase","slice","options","draftAndPublish","pluginOptions","i18n","localized","visible","restrictRelationsTo","prev"],"mappings":"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"}
@@ -180,8 +180,8 @@ const ACTION_TO_STATUS = {
180
180
  ...prev.pluginOptions,
181
181
  ...contentTypeBase.pluginOptions,
182
182
  i18n: {
183
- ...prev.pluginOptions?.i18n ?? {},
184
- ...contentTypeBase.pluginOptions?.i18n ?? {},
183
+ ...prev.pluginOptions?.i18n,
184
+ ...contentTypeBase.pluginOptions?.i18n,
185
185
  localized: schema.options?.localized ?? prev.pluginOptions?.i18n?.localized ?? false
186
186
  }
187
187
  },
@@ -1 +1 @@
1
- {"version":3,"file":"toCTB.mjs","sources":["../../../../../../../admin/src/components/AIChat/lib/transforms/schemas/toCTB.ts"],"sourcesContent":["import isEqual from 'lodash/isEqual';\nimport omit from 'lodash/omit';\nimport pluralize from 'pluralize';\n\nimport type { ContentType, Component, AnyAttribute } from '../../../../../types';\nimport type { Schema, SchemaAttribute } from '../../types/schema';\nimport type { Struct, UID } from '@strapi/types';\n\nconst isPluginContentTypeUid = (uid: string) => uid.startsWith('plugin::');\n\nconst isContentTypeKind = (kind: Schema['kind']): kind is Struct.ContentTypeKind => {\n return kind === 'collectionType' || kind === 'singleType';\n};\n\n/**\n * Plugin / extension content-types use server-derived identity (globalId, collectionName, …).\n * The AI chat uses a simplified shape that would otherwise overwrite those fields incorrectly.\n */\nconst isPluginContentType = (schema: Schema, oldSchema?: ContentType | Component): boolean => {\n if (schema.plugin || isPluginContentTypeUid(schema.uid)) {\n return true;\n }\n if (oldSchema && 'modelType' in oldSchema && oldSchema.modelType === 'contentType') {\n const ct = oldSchema as ContentType;\n return Boolean(ct.plugin) || isPluginContentTypeUid(String(ct.uid));\n }\n return false;\n};\n\nconst ACTION_TO_STATUS: Record<Schema['action'], ContentType['status']> = {\n create: 'NEW',\n remove: 'REMOVED',\n update: 'CHANGED',\n};\n\n/**\n * Creates a new attribute with the specified status\n */\nconst createAttributeWithStatus = (\n name: string,\n attributeData: SchemaAttribute | AnyAttribute,\n status: AnyAttribute['status']\n): AnyAttribute =>\n ({\n ...attributeData,\n name,\n status,\n }) as AnyAttribute;\n\n/**\n * Determines the status of an attribute by comparing new and old versions\n */\nconst determineAttributeStatus = (\n newAttr: Record<string, unknown>,\n oldAttr?: AnyAttribute,\n oldSchema?: ContentType | Component\n): AnyAttribute['status'] => {\n if (!oldAttr) {\n return 'NEW';\n }\n\n // If the schema was already new, don't mark attributes as changed, keep them as new.\n if (oldSchema?.status === 'NEW') {\n return 'NEW';\n }\n\n // Compare attributes without the status field to determine if they've changed\n const newAttrWithoutStatus = omit(newAttr, ['status']);\n const oldAttrWithoutStatus = omit(oldAttr, ['status']);\n\n if (!isEqual(newAttrWithoutStatus, oldAttrWithoutStatus)) {\n return 'CHANGED';\n }\n\n // If unchanged, keep the previous status\n return oldAttr.status;\n};\n\n/**\n * Determines the status of a schema by comparing action and checking if oldSchema exists\n */\nconst transformStatusFromChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType['status'] => {\n // If schema has an action, use the mapped status\n if (schema.action) {\n return ACTION_TO_STATUS[schema.action];\n }\n\n // If oldSchema doesn't exist, it's a new schema\n if (!oldSchema) {\n return 'NEW';\n }\n\n // If no action is specified and oldSchema exists, keep the existing status\n return oldSchema.status;\n};\n\n/**\n * Transform attributes from Chat format to CTB format\n * Also performs a diff to determine the status of each attribute\n */\nexport const transformAttributesFromChatToCTB = (\n { action, attributes }: Schema,\n oldSchema?: ContentType | Component\n): AnyAttribute[] => {\n // If it's a new schema or no oldAttributes provided, all attributes are NEW\n if (action === 'create' || !oldSchema) {\n return Object.entries(attributes).map(([name, attribute]) =>\n createAttributeWithStatus(name, attribute, 'NEW')\n );\n }\n\n // Convert old attributes array to a lookup map for faster access\n const oldAttributesMap = oldSchema.attributes.reduce(\n (acc, attr) => ({ ...acc, [attr.name]: attr }),\n {} as Record<string, AnyAttribute>\n );\n\n // Process current attributes (new and changed)\n const processedAttributes = Object.entries(attributes).map(([name, attr]) => {\n const oldAttr = oldAttributesMap[name];\n const status = determineAttributeStatus({ ...attr, name }, oldAttr, oldSchema);\n\n return createAttributeWithStatus(name, attr, status);\n });\n\n // No need to mark removed attributes if the old schema is new, just remove it from the list\n // TODO: Else a validation error occurs on the backend side.\n if (oldSchema?.status === 'NEW') {\n return processedAttributes;\n }\n\n // Find removed attributes (exist in old but not in new)\n const removedAttributes = Object.entries(oldAttributesMap)\n .filter(([name]) => !attributes[name])\n .map(([name, oldAttr]) => createAttributeWithStatus(name, oldAttr, 'REMOVED'));\n\n // Combine both sets of attributes\n return [...processedAttributes, ...removedAttributes];\n};\n\n/**\n * Transform schema format\n * AI chat -> CTB\n *\n * The AI chat returns a simplified format, and this layer transforms it to be compatible with the CTB reducer.\n *\n * We need to keep track of which changes have been made\n */\nexport const transformChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType | Component => {\n const singularName = pluralize.singular(schema.name).toLowerCase().replace(/ /g, '-');\n const pluralName = pluralize.plural(schema.name).toLowerCase().replace(/ /g, '-');\n\n if (schema.modelType === 'component') {\n return {\n category: schema.category || 'default',\n modelName: singularName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n info: {\n displayName: schema.name,\n description: schema.description,\n // TODO\n // icon: schema.icon,\n },\n modelType: schema.modelType,\n uid: schema.uid as UID.Component,\n collectionName: pluralName,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n } satisfies Component;\n }\n\n const previousContentType = oldSchema?.modelType === 'contentType' ? oldSchema : undefined;\n const kind = isContentTypeKind(schema.kind) ? schema.kind : 'collectionType';\n\n const contentTypeBase = {\n uid: schema.uid as UID.ContentType,\n modelType: 'contentType',\n modelName: singularName,\n kind,\n info: {\n displayName: schema.name.charAt(0).toUpperCase() + schema.name.slice(1),\n // Always keep the old by default\n singularName: previousContentType?.info.singularName ?? singularName,\n // Always keep the old by default\n pluralName: previousContentType?.info.pluralName ?? pluralName,\n },\n collectionName: pluralName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n options: {\n draftAndPublish: schema.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n i18n: {\n localized: schema.options?.localized ?? false,\n },\n },\n visible: true,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n restrictRelationsTo: null, // TODO: not sure what this is about\n } satisfies ContentType;\n\n if (\n isPluginContentType(schema, oldSchema) &&\n oldSchema &&\n oldSchema.modelType === 'contentType'\n ) {\n const prev = oldSchema as ContentType;\n return {\n ...contentTypeBase,\n plugin: prev.plugin ?? schema.plugin,\n globalId: prev.globalId,\n modelName: prev.modelName,\n collectionName: prev.collectionName,\n info: {\n ...contentTypeBase.info,\n singularName: prev.info.singularName,\n pluralName: prev.info.pluralName,\n },\n options: {\n ...prev.options,\n ...contentTypeBase.options,\n draftAndPublish: schema.options?.draftAndPublish ?? prev.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n ...prev.pluginOptions,\n ...contentTypeBase.pluginOptions,\n i18n: {\n ...((prev.pluginOptions?.i18n as Record<string, unknown> | undefined) ?? {}),\n ...((contentTypeBase.pluginOptions?.i18n as Record<string, unknown> | undefined) ?? {}),\n localized:\n schema.options?.localized ??\n (prev.pluginOptions?.i18n as { localized?: boolean } | undefined)?.localized ??\n false,\n },\n },\n visible: prev.visible,\n restrictRelationsTo: prev.restrictRelationsTo,\n } satisfies ContentType;\n }\n\n if (isPluginContentType(schema, oldSchema) && schema.plugin) {\n return {\n ...contentTypeBase,\n plugin: schema.plugin,\n } satisfies ContentType;\n }\n\n return contentTypeBase;\n};\n"],"names":["isPluginContentTypeUid","uid","startsWith","isContentTypeKind","kind","isPluginContentType","schema","oldSchema","plugin","modelType","ct","Boolean","String","ACTION_TO_STATUS","create","remove","update","createAttributeWithStatus","name","attributeData","status","determineAttributeStatus","newAttr","oldAttr","newAttrWithoutStatus","omit","oldAttrWithoutStatus","isEqual","transformStatusFromChatToCTB","action","transformAttributesFromChatToCTB","attributes","Object","entries","map","attribute","oldAttributesMap","reduce","acc","attr","processedAttributes","removedAttributes","filter","transformChatToCTB","singularName","pluralize","singular","toLowerCase","replace","pluralName","plural","category","modelName","info","displayName","description","collectionName","globalId","previousContentType","undefined","contentTypeBase","charAt","toUpperCase","slice","options","draftAndPublish","pluginOptions","i18n","localized","visible","restrictRelationsTo","prev"],"mappings":"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"}
1
+ {"version":3,"file":"toCTB.mjs","sources":["../../../../../../../admin/src/components/AIChat/lib/transforms/schemas/toCTB.ts"],"sourcesContent":["import isEqual from 'lodash/isEqual';\nimport omit from 'lodash/omit';\nimport pluralize from 'pluralize';\n\nimport type { ContentType, Component, AnyAttribute } from '../../../../../types';\nimport type { Schema, SchemaAttribute } from '../../types/schema';\nimport type { Struct, UID } from '@strapi/types';\n\nconst isPluginContentTypeUid = (uid: string) => uid.startsWith('plugin::');\n\nconst isContentTypeKind = (kind: Schema['kind']): kind is Struct.ContentTypeKind => {\n return kind === 'collectionType' || kind === 'singleType';\n};\n\n/**\n * Plugin / extension content-types use server-derived identity (globalId, collectionName, …).\n * The AI chat uses a simplified shape that would otherwise overwrite those fields incorrectly.\n */\nconst isPluginContentType = (schema: Schema, oldSchema?: ContentType | Component): boolean => {\n if (schema.plugin || isPluginContentTypeUid(schema.uid)) {\n return true;\n }\n if (oldSchema && 'modelType' in oldSchema && oldSchema.modelType === 'contentType') {\n const ct = oldSchema as ContentType;\n return Boolean(ct.plugin) || isPluginContentTypeUid(String(ct.uid));\n }\n return false;\n};\n\nconst ACTION_TO_STATUS: Record<Schema['action'], ContentType['status']> = {\n create: 'NEW',\n remove: 'REMOVED',\n update: 'CHANGED',\n};\n\n/**\n * Creates a new attribute with the specified status\n */\nconst createAttributeWithStatus = (\n name: string,\n attributeData: SchemaAttribute | AnyAttribute,\n status: AnyAttribute['status']\n): AnyAttribute =>\n ({\n ...attributeData,\n name,\n status,\n }) as AnyAttribute;\n\n/**\n * Determines the status of an attribute by comparing new and old versions\n */\nconst determineAttributeStatus = (\n newAttr: Record<string, unknown>,\n oldAttr?: AnyAttribute,\n oldSchema?: ContentType | Component\n): AnyAttribute['status'] => {\n if (!oldAttr) {\n return 'NEW';\n }\n\n // If the schema was already new, don't mark attributes as changed, keep them as new.\n if (oldSchema?.status === 'NEW') {\n return 'NEW';\n }\n\n // Compare attributes without the status field to determine if they've changed\n const newAttrWithoutStatus = omit(newAttr, ['status']);\n const oldAttrWithoutStatus = omit(oldAttr, ['status']);\n\n if (!isEqual(newAttrWithoutStatus, oldAttrWithoutStatus)) {\n return 'CHANGED';\n }\n\n // If unchanged, keep the previous status\n return oldAttr.status;\n};\n\n/**\n * Determines the status of a schema by comparing action and checking if oldSchema exists\n */\nconst transformStatusFromChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType['status'] => {\n // If schema has an action, use the mapped status\n if (schema.action) {\n return ACTION_TO_STATUS[schema.action];\n }\n\n // If oldSchema doesn't exist, it's a new schema\n if (!oldSchema) {\n return 'NEW';\n }\n\n // If no action is specified and oldSchema exists, keep the existing status\n return oldSchema.status;\n};\n\n/**\n * Transform attributes from Chat format to CTB format\n * Also performs a diff to determine the status of each attribute\n */\nexport const transformAttributesFromChatToCTB = (\n { action, attributes }: Schema,\n oldSchema?: ContentType | Component\n): AnyAttribute[] => {\n // If it's a new schema or no oldAttributes provided, all attributes are NEW\n if (action === 'create' || !oldSchema) {\n return Object.entries(attributes).map(([name, attribute]) =>\n createAttributeWithStatus(name, attribute, 'NEW')\n );\n }\n\n // Convert old attributes array to a lookup map for faster access\n const oldAttributesMap = oldSchema.attributes.reduce(\n (acc, attr) => ({ ...acc, [attr.name]: attr }),\n {} as Record<string, AnyAttribute>\n );\n\n // Process current attributes (new and changed)\n const processedAttributes = Object.entries(attributes).map(([name, attr]) => {\n const oldAttr = oldAttributesMap[name];\n const status = determineAttributeStatus({ ...attr, name }, oldAttr, oldSchema);\n\n return createAttributeWithStatus(name, attr, status);\n });\n\n // No need to mark removed attributes if the old schema is new, just remove it from the list\n // TODO: Else a validation error occurs on the backend side.\n if (oldSchema?.status === 'NEW') {\n return processedAttributes;\n }\n\n // Find removed attributes (exist in old but not in new)\n const removedAttributes = Object.entries(oldAttributesMap)\n .filter(([name]) => !attributes[name])\n .map(([name, oldAttr]) => createAttributeWithStatus(name, oldAttr, 'REMOVED'));\n\n // Combine both sets of attributes\n return [...processedAttributes, ...removedAttributes];\n};\n\n/**\n * Transform schema format\n * AI chat -> CTB\n *\n * The AI chat returns a simplified format, and this layer transforms it to be compatible with the CTB reducer.\n *\n * We need to keep track of which changes have been made\n */\nexport const transformChatToCTB = (\n schema: Schema,\n oldSchema?: ContentType | Component\n): ContentType | Component => {\n const singularName = pluralize.singular(schema.name).toLowerCase().replace(/ /g, '-');\n const pluralName = pluralize.plural(schema.name).toLowerCase().replace(/ /g, '-');\n\n if (schema.modelType === 'component') {\n return {\n category: schema.category || 'default',\n modelName: singularName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n info: {\n displayName: schema.name,\n description: schema.description,\n // TODO\n // icon: schema.icon,\n },\n modelType: schema.modelType,\n uid: schema.uid as UID.Component,\n collectionName: pluralName,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n } satisfies Component;\n }\n\n const previousContentType = oldSchema?.modelType === 'contentType' ? oldSchema : undefined;\n const kind = isContentTypeKind(schema.kind) ? schema.kind : 'collectionType';\n\n const contentTypeBase = {\n uid: schema.uid as UID.ContentType,\n modelType: 'contentType',\n modelName: singularName,\n kind,\n info: {\n displayName: schema.name.charAt(0).toUpperCase() + schema.name.slice(1),\n // Always keep the old by default\n singularName: previousContentType?.info.singularName ?? singularName,\n // Always keep the old by default\n pluralName: previousContentType?.info.pluralName ?? pluralName,\n },\n collectionName: pluralName,\n attributes: transformAttributesFromChatToCTB(schema, oldSchema),\n options: {\n draftAndPublish: schema.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n i18n: {\n localized: schema.options?.localized ?? false,\n },\n },\n visible: true,\n status: transformStatusFromChatToCTB(schema, oldSchema),\n globalId: singularName,\n restrictRelationsTo: null, // TODO: not sure what this is about\n } satisfies ContentType;\n\n if (\n isPluginContentType(schema, oldSchema) &&\n oldSchema &&\n oldSchema.modelType === 'contentType'\n ) {\n const prev = oldSchema as ContentType;\n return {\n ...contentTypeBase,\n plugin: prev.plugin ?? schema.plugin,\n globalId: prev.globalId,\n modelName: prev.modelName,\n collectionName: prev.collectionName,\n info: {\n ...contentTypeBase.info,\n singularName: prev.info.singularName,\n pluralName: prev.info.pluralName,\n },\n options: {\n ...prev.options,\n ...contentTypeBase.options,\n draftAndPublish: schema.options?.draftAndPublish ?? prev.options?.draftAndPublish ?? true,\n },\n pluginOptions: {\n ...prev.pluginOptions,\n ...contentTypeBase.pluginOptions,\n i18n: {\n ...(prev.pluginOptions?.i18n as Record<string, unknown> | undefined),\n ...(contentTypeBase.pluginOptions?.i18n as Record<string, unknown> | undefined),\n localized:\n schema.options?.localized ??\n (prev.pluginOptions?.i18n as { localized?: boolean } | undefined)?.localized ??\n false,\n },\n },\n visible: prev.visible,\n restrictRelationsTo: prev.restrictRelationsTo,\n } satisfies ContentType;\n }\n\n if (isPluginContentType(schema, oldSchema) && schema.plugin) {\n return {\n ...contentTypeBase,\n plugin: schema.plugin,\n } satisfies ContentType;\n }\n\n return contentTypeBase;\n};\n"],"names":["isPluginContentTypeUid","uid","startsWith","isContentTypeKind","kind","isPluginContentType","schema","oldSchema","plugin","modelType","ct","Boolean","String","ACTION_TO_STATUS","create","remove","update","createAttributeWithStatus","name","attributeData","status","determineAttributeStatus","newAttr","oldAttr","newAttrWithoutStatus","omit","oldAttrWithoutStatus","isEqual","transformStatusFromChatToCTB","action","transformAttributesFromChatToCTB","attributes","Object","entries","map","attribute","oldAttributesMap","reduce","acc","attr","processedAttributes","removedAttributes","filter","transformChatToCTB","singularName","pluralize","singular","toLowerCase","replace","pluralName","plural","category","modelName","info","displayName","description","collectionName","globalId","previousContentType","undefined","contentTypeBase","charAt","toUpperCase","slice","options","draftAndPublish","pluginOptions","i18n","localized","visible","restrictRelationsTo","prev"],"mappings":"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"}
@@ -18,7 +18,7 @@ var useCTBSession = require('./useCTBSession.js');
18
18
  const { sessionId } = useCTBSession.useCTBSession();
19
19
  const trackUsage = React.useCallback((event, properties)=>{
20
20
  const enhancedProperties = {
21
- ...properties ?? {},
21
+ ...properties,
22
22
  ctbSessionId: sessionId
23
23
  };
24
24
  // The admin tracking API is typed for declared events, but CTB emits extension events too.
@@ -1 +1 @@
1
- {"version":3,"file":"useCTBTracking.js","sources":["../../../../admin/src/components/CTBSession/useCTBTracking.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport { useTracking } from '@strapi/admin/strapi-admin';\n\nimport { useCTBSession } from './useCTBSession';\n\ntype TrackUsageWithDynamicEvent = (\n event: string,\n properties: Record<string, unknown>\n) => ReturnType<ReturnType<typeof useTracking>['trackUsage']>;\n\n/**\n * Hook that provides tracking functionality with automatic CTB session ID inclusion.\n * This version accepts arbitrary event names (string) to allow feature-specific\n * events that are not yet declared in the central tracking typings.\n *\n * Note: this intentionally relaxes TypeScript restrictions so callers can\n * emit new tracking event names without needing to update the upstream\n * tracking type definitions. The session ID is merged into the properties\n * object before forwarding to the original tracking implementation.\n */\nexport const useCTBTracking = () => {\n const { trackUsage: originalTrackUsage } = useTracking();\n const { sessionId } = useCTBSession();\n\n const trackUsage = useCallback(\n (event: string, properties?: Record<string, unknown>) => {\n const enhancedProperties = {\n ...(properties ?? {}),\n ctbSessionId: sessionId,\n };\n\n // The admin tracking API is typed for declared events, but CTB emits extension events too.\n const trackDynamicEvent = originalTrackUsage as unknown as TrackUsageWithDynamicEvent;\n\n return trackDynamicEvent(event, enhancedProperties);\n },\n [originalTrackUsage, sessionId]\n );\n\n return { trackUsage };\n};\n"],"names":["useCTBTracking","trackUsage","originalTrackUsage","useTracking","sessionId","useCTBSession","useCallback","event","properties","enhancedProperties","ctbSessionId","trackDynamicEvent"],"mappings":";;;;;;AAWA;;;;;;;;;UAUaA,cAAAA,GAAiB,IAAA;AAC5B,IAAA,MAAM,EAAEC,UAAAA,EAAYC,kBAAkB,EAAE,GAAGC,uBAAAA,EAAAA;IAC3C,MAAM,EAAEC,SAAS,EAAE,GAAGC,2BAAAA,EAAAA;IAEtB,MAAMJ,UAAAA,GAAaK,iBAAAA,CACjB,CAACC,KAAAA,EAAeC,UAAAA,GAAAA;AACd,QAAA,MAAMC,kBAAAA,GAAqB;YACzB,GAAID,UAAAA,IAAc,EAAE;YACpBE,YAAAA,EAAcN;AAChB,SAAA;;AAGA,QAAA,MAAMO,iBAAAA,GAAoBT,kBAAAA;AAE1B,QAAA,OAAOS,kBAAkBJ,KAAAA,EAAOE,kBAAAA,CAAAA;IAClC,CAAA,EACA;AAACP,QAAAA,kBAAAA;AAAoBE,QAAAA;AAAU,KAAA,CAAA;IAGjC,OAAO;AAAEH,QAAAA;AAAW,KAAA;AACtB;;;;"}
1
+ {"version":3,"file":"useCTBTracking.js","sources":["../../../../admin/src/components/CTBSession/useCTBTracking.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport { useTracking } from '@strapi/admin/strapi-admin';\n\nimport { useCTBSession } from './useCTBSession';\n\ntype TrackUsageWithDynamicEvent = (\n event: string,\n properties: Record<string, unknown>\n) => ReturnType<ReturnType<typeof useTracking>['trackUsage']>;\n\n/**\n * Hook that provides tracking functionality with automatic CTB session ID inclusion.\n * This version accepts arbitrary event names (string) to allow feature-specific\n * events that are not yet declared in the central tracking typings.\n *\n * Note: this intentionally relaxes TypeScript restrictions so callers can\n * emit new tracking event names without needing to update the upstream\n * tracking type definitions. The session ID is merged into the properties\n * object before forwarding to the original tracking implementation.\n */\nexport const useCTBTracking = () => {\n const { trackUsage: originalTrackUsage } = useTracking();\n const { sessionId } = useCTBSession();\n\n const trackUsage = useCallback(\n (event: string, properties?: Record<string, unknown>) => {\n const enhancedProperties = {\n ...properties,\n ctbSessionId: sessionId,\n };\n\n // The admin tracking API is typed for declared events, but CTB emits extension events too.\n const trackDynamicEvent = originalTrackUsage as unknown as TrackUsageWithDynamicEvent;\n\n return trackDynamicEvent(event, enhancedProperties);\n },\n [originalTrackUsage, sessionId]\n );\n\n return { trackUsage };\n};\n"],"names":["useCTBTracking","trackUsage","originalTrackUsage","useTracking","sessionId","useCTBSession","useCallback","event","properties","enhancedProperties","ctbSessionId","trackDynamicEvent"],"mappings":";;;;;;AAWA;;;;;;;;;UAUaA,cAAAA,GAAiB,IAAA;AAC5B,IAAA,MAAM,EAAEC,UAAAA,EAAYC,kBAAkB,EAAE,GAAGC,uBAAAA,EAAAA;IAC3C,MAAM,EAAEC,SAAS,EAAE,GAAGC,2BAAAA,EAAAA;IAEtB,MAAMJ,UAAAA,GAAaK,iBAAAA,CACjB,CAACC,KAAAA,EAAeC,UAAAA,GAAAA;AACd,QAAA,MAAMC,kBAAAA,GAAqB;AACzB,YAAA,GAAGD,UAAU;YACbE,YAAAA,EAAcN;AAChB,SAAA;;AAGA,QAAA,MAAMO,iBAAAA,GAAoBT,kBAAAA;AAE1B,QAAA,OAAOS,kBAAkBJ,KAAAA,EAAOE,kBAAAA,CAAAA;IAClC,CAAA,EACA;AAACP,QAAAA,kBAAAA;AAAoBE,QAAAA;AAAU,KAAA,CAAA;IAGjC,OAAO;AAAEH,QAAAA;AAAW,KAAA;AACtB;;;;"}
@@ -16,7 +16,7 @@ import { useCTBSession } from './useCTBSession.mjs';
16
16
  const { sessionId } = useCTBSession();
17
17
  const trackUsage = useCallback((event, properties)=>{
18
18
  const enhancedProperties = {
19
- ...properties ?? {},
19
+ ...properties,
20
20
  ctbSessionId: sessionId
21
21
  };
22
22
  // The admin tracking API is typed for declared events, but CTB emits extension events too.
@@ -1 +1 @@
1
- {"version":3,"file":"useCTBTracking.mjs","sources":["../../../../admin/src/components/CTBSession/useCTBTracking.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport { useTracking } from '@strapi/admin/strapi-admin';\n\nimport { useCTBSession } from './useCTBSession';\n\ntype TrackUsageWithDynamicEvent = (\n event: string,\n properties: Record<string, unknown>\n) => ReturnType<ReturnType<typeof useTracking>['trackUsage']>;\n\n/**\n * Hook that provides tracking functionality with automatic CTB session ID inclusion.\n * This version accepts arbitrary event names (string) to allow feature-specific\n * events that are not yet declared in the central tracking typings.\n *\n * Note: this intentionally relaxes TypeScript restrictions so callers can\n * emit new tracking event names without needing to update the upstream\n * tracking type definitions. The session ID is merged into the properties\n * object before forwarding to the original tracking implementation.\n */\nexport const useCTBTracking = () => {\n const { trackUsage: originalTrackUsage } = useTracking();\n const { sessionId } = useCTBSession();\n\n const trackUsage = useCallback(\n (event: string, properties?: Record<string, unknown>) => {\n const enhancedProperties = {\n ...(properties ?? {}),\n ctbSessionId: sessionId,\n };\n\n // The admin tracking API is typed for declared events, but CTB emits extension events too.\n const trackDynamicEvent = originalTrackUsage as unknown as TrackUsageWithDynamicEvent;\n\n return trackDynamicEvent(event, enhancedProperties);\n },\n [originalTrackUsage, sessionId]\n );\n\n return { trackUsage };\n};\n"],"names":["useCTBTracking","trackUsage","originalTrackUsage","useTracking","sessionId","useCTBSession","useCallback","event","properties","enhancedProperties","ctbSessionId","trackDynamicEvent"],"mappings":";;;;AAWA;;;;;;;;;UAUaA,cAAAA,GAAiB,IAAA;AAC5B,IAAA,MAAM,EAAEC,UAAAA,EAAYC,kBAAkB,EAAE,GAAGC,WAAAA,EAAAA;IAC3C,MAAM,EAAEC,SAAS,EAAE,GAAGC,aAAAA,EAAAA;IAEtB,MAAMJ,UAAAA,GAAaK,WAAAA,CACjB,CAACC,KAAAA,EAAeC,UAAAA,GAAAA;AACd,QAAA,MAAMC,kBAAAA,GAAqB;YACzB,GAAID,UAAAA,IAAc,EAAE;YACpBE,YAAAA,EAAcN;AAChB,SAAA;;AAGA,QAAA,MAAMO,iBAAAA,GAAoBT,kBAAAA;AAE1B,QAAA,OAAOS,kBAAkBJ,KAAAA,EAAOE,kBAAAA,CAAAA;IAClC,CAAA,EACA;AAACP,QAAAA,kBAAAA;AAAoBE,QAAAA;AAAU,KAAA,CAAA;IAGjC,OAAO;AAAEH,QAAAA;AAAW,KAAA;AACtB;;;;"}
1
+ {"version":3,"file":"useCTBTracking.mjs","sources":["../../../../admin/src/components/CTBSession/useCTBTracking.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport { useTracking } from '@strapi/admin/strapi-admin';\n\nimport { useCTBSession } from './useCTBSession';\n\ntype TrackUsageWithDynamicEvent = (\n event: string,\n properties: Record<string, unknown>\n) => ReturnType<ReturnType<typeof useTracking>['trackUsage']>;\n\n/**\n * Hook that provides tracking functionality with automatic CTB session ID inclusion.\n * This version accepts arbitrary event names (string) to allow feature-specific\n * events that are not yet declared in the central tracking typings.\n *\n * Note: this intentionally relaxes TypeScript restrictions so callers can\n * emit new tracking event names without needing to update the upstream\n * tracking type definitions. The session ID is merged into the properties\n * object before forwarding to the original tracking implementation.\n */\nexport const useCTBTracking = () => {\n const { trackUsage: originalTrackUsage } = useTracking();\n const { sessionId } = useCTBSession();\n\n const trackUsage = useCallback(\n (event: string, properties?: Record<string, unknown>) => {\n const enhancedProperties = {\n ...properties,\n ctbSessionId: sessionId,\n };\n\n // The admin tracking API is typed for declared events, but CTB emits extension events too.\n const trackDynamicEvent = originalTrackUsage as unknown as TrackUsageWithDynamicEvent;\n\n return trackDynamicEvent(event, enhancedProperties);\n },\n [originalTrackUsage, sessionId]\n );\n\n return { trackUsage };\n};\n"],"names":["useCTBTracking","trackUsage","originalTrackUsage","useTracking","sessionId","useCTBSession","useCallback","event","properties","enhancedProperties","ctbSessionId","trackDynamicEvent"],"mappings":";;;;AAWA;;;;;;;;;UAUaA,cAAAA,GAAiB,IAAA;AAC5B,IAAA,MAAM,EAAEC,UAAAA,EAAYC,kBAAkB,EAAE,GAAGC,WAAAA,EAAAA;IAC3C,MAAM,EAAEC,SAAS,EAAE,GAAGC,aAAAA,EAAAA;IAEtB,MAAMJ,UAAAA,GAAaK,WAAAA,CACjB,CAACC,KAAAA,EAAeC,UAAAA,GAAAA;AACd,QAAA,MAAMC,kBAAAA,GAAqB;AACzB,YAAA,GAAGD,UAAU;YACbE,YAAAA,EAAcN;AAChB,SAAA;;AAGA,QAAA,MAAMO,iBAAAA,GAAoBT,kBAAAA;AAE1B,QAAA,OAAOS,kBAAkBJ,KAAAA,EAAOE,kBAAAA,CAAAA;IAClC,CAAA,EACA;AAACP,QAAAA,kBAAAA;AAAoBE,QAAAA;AAAU,KAAA,CAAA;IAGjC,OAAO;AAAEH,QAAAA;AAAW,KAAA;AACtB;;;;"}
@@ -277,6 +277,7 @@ const slice = undoRedo.createUndoRedoSlice({
277
277
  targetUid: attributeToSet.target
278
278
  });
279
279
  const previousTargetAttributeIndex = findAttributeIndex(previousTarget, previousAttribute.targetAttribute ?? '');
280
+ const previousTargetAttribute = previousTargetAttributeIndex !== -1 ? previousTarget.attributes[previousTargetAttributeIndex] : undefined;
280
281
  // remove old targetAttribute
281
282
  if (previousAttribute.targetAttribute) {
282
283
  removeAttributeByName(previousTarget, previousAttribute.targetAttribute);
@@ -292,6 +293,9 @@ const slice = undoRedo.createUndoRedoSlice({
292
293
  target: type.uid,
293
294
  private: previousAttribute.private ?? attributeToSet.private,
294
295
  pluginOptions: previousAttribute.pluginOptions ?? attributeToSet.pluginOptions,
296
+ ...previousTarget.uid === newTarget.uid && previousTargetAttribute?.conditions ? {
297
+ conditions: previousTargetAttribute.conditions
298
+ } : {},
295
299
  status: 'CHANGED'
296
300
  };
297
301
  // create or recreate(at old index) targetAttribute