mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 21:54:56 +00:00
146 lines
3.5 KiB
TypeScript
146 lines
3.5 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react'
|
|
import { useKV } from '@/hooks/use-kv'
|
|
import type { DataSourceConfig } from './schema'
|
|
|
|
export function useJSONDataSource<T = unknown>(
|
|
id: string,
|
|
config: DataSourceConfig<T>
|
|
) {
|
|
const kvConfig = config.type === 'kv' ? config.config : undefined
|
|
const apiConfig = config.type === 'api' ? config.config : undefined
|
|
const computedConfig = config.type === 'computed' ? config.config : undefined
|
|
const defaultValue =
|
|
config.type === 'static' ? config.config : config.config?.defaultValue
|
|
|
|
const [kvValue, setKVValue] = useKV<T>(
|
|
kvConfig?.key || id,
|
|
(kvConfig?.defaultValue ?? defaultValue) as T
|
|
)
|
|
const [apiValue, setApiValue] = useState<T | undefined>(defaultValue)
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState<Error | null>(null)
|
|
|
|
const fetchAPI = useCallback(async () => {
|
|
if (config.type !== 'api' || !apiConfig?.url) return
|
|
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
try {
|
|
const response = await fetch(apiConfig.url)
|
|
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
|
let data = await response.json()
|
|
|
|
if (apiConfig.transform) {
|
|
data = apiConfig.transform(data)
|
|
}
|
|
|
|
setApiValue(data)
|
|
} catch (err) {
|
|
setError(err as Error)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}, [apiConfig, config.type])
|
|
|
|
useEffect(() => {
|
|
if (config.type === 'api') {
|
|
fetchAPI()
|
|
}
|
|
}, [config.type, fetchAPI])
|
|
|
|
const getValue = () => {
|
|
switch (config.type) {
|
|
case 'kv':
|
|
return kvValue
|
|
case 'api':
|
|
return apiValue
|
|
case 'static':
|
|
return config.config
|
|
case 'computed':
|
|
return computedConfig?.defaultValue
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
const setValue = (newValue: any) => {
|
|
switch (config.type) {
|
|
case 'kv':
|
|
setKVValue(newValue)
|
|
break
|
|
case 'api':
|
|
setApiValue(newValue)
|
|
break
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
return {
|
|
value: getValue(),
|
|
setValue,
|
|
loading,
|
|
error,
|
|
refetch: fetchAPI,
|
|
}
|
|
}
|
|
|
|
export function useJSONDataSources<T = unknown>(
|
|
sources: Record<string, DataSourceConfig<T>>
|
|
) {
|
|
const [dataMap, setDataMap] = useState<Record<string, any>>({})
|
|
const [loadingMap, setLoadingMap] = useState<Record<string, boolean>>({})
|
|
const [errorMap, setErrorMap] = useState<Record<string, Error | null>>({})
|
|
|
|
const sourceIds = Object.keys(sources)
|
|
|
|
const updateData = useCallback((id: string, value: any) => {
|
|
setDataMap((prev) => ({ ...prev, [id]: value }))
|
|
}, [])
|
|
|
|
const getData = useCallback((id: string) => {
|
|
return dataMap[id]
|
|
}, [dataMap])
|
|
|
|
useEffect(() => {
|
|
sourceIds.forEach((id) => {
|
|
const config = sources[id]
|
|
|
|
if (config.type === 'static') {
|
|
updateData(id, config.config)
|
|
}
|
|
})
|
|
}, [sourceIds])
|
|
|
|
return {
|
|
dataMap,
|
|
loadingMap,
|
|
errorMap,
|
|
updateData,
|
|
getData,
|
|
}
|
|
}
|
|
|
|
export function useJSONActions() {
|
|
const [actionHandlers, setActionHandlers] = useState<Record<string, (...args: any[]) => void>>({})
|
|
|
|
const registerAction = useCallback((id: string, handler: (...args: any[]) => void) => {
|
|
setActionHandlers((prev) => ({ ...prev, [id]: handler }))
|
|
}, [])
|
|
|
|
const executeAction = useCallback((id: string, ...args: any[]) => {
|
|
const handler = actionHandlers[id]
|
|
if (handler) {
|
|
handler(...args)
|
|
} else {
|
|
console.warn(`Action handler not found: ${id}`)
|
|
}
|
|
}, [actionHandlers])
|
|
|
|
return {
|
|
registerAction,
|
|
executeAction,
|
|
}
|
|
}
|