import type { BannerListResponse, BannerResponse, GetExploreAppsLearnDifyResponse, GetExploreAppsResponse, RecommendedAppDetailResponse, RecommendedAppInfoResponse, RecommendedAppResponse, } from '@dify/contracts/api/console/explore/types.gen' import type { Banner } from '@/models/app' import type { App, AppCategory } from '@/models/explore' import type { AppIconType } from '@/types/app' import { consoleClient } from './client' type ExploreAppsResponse = { categories: AppCategory[] recommended_apps: App[] } type LearnDifyAppsResponse = { recommended_apps: App[] } type ExploreAppDetailResponse = { id: string name: string icon: string icon_background: string mode: string export_data: string can_trial: boolean } const isRecord = (value: unknown): value is Record => { return typeof value === 'object' && value !== null && !Array.isArray(value) } const getValue = (source: object, key: string): unknown => { return Reflect.get(source, key) } const getStringProperty = (source: object, key: string, fallback = '') => { const value = getValue(source, key) return typeof value === 'string' ? value : fallback } const normalizeAppMode = (value: unknown) => { return typeof value === 'string' ? value : '' } const isAppIconType = (value: unknown): value is AppIconType => { return value === 'image' || value === 'emoji' || value === 'link' } const normalizeAppIconType = (value: unknown) => { return isAppIconType(value) ? value : null } const normalizeAppBasicInfo = ( source: RecommendedAppInfoResponse | null | undefined, fallbackId: string, ): App['app'] => { return { id: source?.id ?? fallbackId, mode: normalizeAppMode(source?.mode), icon_type: normalizeAppIconType(source?.icon_type), icon: source?.icon ?? '', icon_background: source?.icon_background ?? '', icon_url: source?.icon_url ?? '', name: source?.name ?? '', description: '', use_icon_as_answer_icon: false, } } const normalizeRecommendedApp = (app: RecommendedAppResponse): App => { return { app: normalizeAppBasicInfo(app.app, app.app_id), app_id: app.app_id, description: app.description ?? '', copyright: app.copyright ?? '', privacy_policy: app.privacy_policy ?? null, custom_disclaimer: app.custom_disclaimer ?? null, categories: app.categories ?? [], position: app.position ?? 0, is_listed: app.is_listed ?? false, install_count: 0, installed: false, editable: false, is_agent: false, can_trial: app.can_trial, } } const normalizeExploreAppsResponse = (response: GetExploreAppsResponse): ExploreAppsResponse => { return { categories: response.categories, recommended_apps: response.recommended_apps.map(normalizeRecommendedApp), } } const normalizeLearnDifyAppsResponse = ( response: GetExploreAppsLearnDifyResponse, ): LearnDifyAppsResponse => { return { recommended_apps: response.recommended_apps.map(normalizeRecommendedApp), } } const normalizeAppDetail = (response: RecommendedAppDetailResponse): ExploreAppDetailResponse => { return { id: response.id, name: response.name, icon: response.icon ?? '', icon_background: response.icon_background ?? '', mode: normalizeAppMode(response.mode), export_data: response.export_data, can_trial: response.can_trial, } } const normalizeBannerContent = (content: unknown): Banner['content'] => { const record = isRecord(content) ? content : {} return { category: getStringProperty(record, 'category'), title: getStringProperty(record, 'title'), description: getStringProperty(record, 'description'), 'img-src': getStringProperty(record, 'img-src'), } } const normalizeBanner = (banner: BannerResponse): Banner => { return { id: banner.id, content: normalizeBannerContent(banner.content), link: banner.link ?? '', sort: banner.sort, status: banner.status, created_at: banner.created_at ?? '', } } const normalizeBannersResponse = (response: BannerListResponse): Banner[] => { return response.map(normalizeBanner) } export const fetchAppList = (language?: string) => { if (!language) return consoleClient.explore.apps.get({}).then(normalizeExploreAppsResponse) return consoleClient.explore.apps .get({ query: { language }, }) .then(normalizeExploreAppsResponse) } export const fetchLearnDifyAppList = (language?: string) => { if (!language) return consoleClient.explore.apps.learnDify.get({}).then(normalizeLearnDifyAppsResponse) return consoleClient.explore.apps.learnDify .get({ query: { language }, }) .then(normalizeLearnDifyAppsResponse) } export const fetchAppDetail = async (id: string): Promise => { const response = await consoleClient.explore.apps.byAppId.get({ params: { app_id: id }, }) if (!response) throw new Error('Recommended app not found') return normalizeAppDetail(response) } export const fetchInstalledAppList = (appId?: string | null) => { if (!appId) return consoleClient.installedApps.get({}) return consoleClient.installedApps.get({ query: { app_id: appId }, }) } export const fetchBanners = (language?: string) => { if (!language) return consoleClient.explore.banners.get({}).then(normalizeBannersResponse) return consoleClient.explore.banners .get({ query: { language }, }) .then(normalizeBannersResponse) }