mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 22:48:17 +00:00
refactor(storage-providers): streamline provider handling and remove unused types
Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
@@ -125,11 +125,22 @@ export class SettingService {
|
||||
const activeIdRaw = await this.get('builder.storage.activeProvider', options)
|
||||
const activeId = typeof activeIdRaw === 'string' && activeIdRaw.trim().length > 0 ? activeIdRaw.trim() : null
|
||||
|
||||
if (!activeId) {
|
||||
return null
|
||||
// If activeId exists and matches, return it
|
||||
if (activeId) {
|
||||
const found = providers.find((provider) => provider.id === activeId) ?? null
|
||||
if (found) return found
|
||||
}
|
||||
|
||||
return providers.find((provider) => provider.id === activeId) ?? null
|
||||
// Fallback: if there is exactly one provider, automatically set it active and persist the setting
|
||||
if (providers.length === 1) {
|
||||
const only = providers[0]
|
||||
// Persist synchronously; ignore schema sensitivity (it's non-sensitive)
|
||||
const setOptions = options ? { ...options, isSensitive: false } : { isSensitive: false }
|
||||
await this.set('builder.storage.activeProvider', only.id, setOptions)
|
||||
return only
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
async set<K extends SettingKeyType>(key: K, value: SettingValueMap[K], options: SetSettingOptions): Promise<void>
|
||||
|
||||
@@ -58,12 +58,7 @@ export const ProviderCard: FC<ProviderCardProps> = ({ provider, isActive, onEdit
|
||||
case 'github': {
|
||||
return cfg.repo || 'Not configured'
|
||||
}
|
||||
case 'local': {
|
||||
return cfg.path || 'Not configured'
|
||||
}
|
||||
case 'eagle': {
|
||||
return cfg.libraryPath || 'Not configured'
|
||||
}
|
||||
|
||||
default: {
|
||||
return 'Storage provider'
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ export function StorageProvidersManager() {
|
||||
}
|
||||
// New provider
|
||||
const result = [...prev, updatedProvider]
|
||||
// Set as active if it's the first provider
|
||||
if (!activeProviderId) {
|
||||
// Set as active ONLY if it's the very first provider
|
||||
if (prev.length === 0) {
|
||||
setActiveProviderId(updatedProvider.id)
|
||||
}
|
||||
return result
|
||||
|
||||
@@ -5,7 +5,7 @@ export const STORAGE_SETTING_KEYS = {
|
||||
activeProvider: 'builder.storage.activeProvider',
|
||||
} as const
|
||||
|
||||
export const STORAGE_PROVIDER_TYPES: readonly StorageProviderType[] = ['s3', 'github', 'local', 'eagle']
|
||||
export const STORAGE_PROVIDER_TYPES: readonly StorageProviderType[] = ['s3', 'github']
|
||||
|
||||
export const STORAGE_PROVIDER_TYPE_OPTIONS: ReadonlyArray<{
|
||||
value: StorageProviderType
|
||||
@@ -13,8 +13,6 @@ export const STORAGE_PROVIDER_TYPE_OPTIONS: ReadonlyArray<{
|
||||
}> = [
|
||||
{ value: 's3', label: 'S3 / 兼容对象存储' },
|
||||
{ value: 'github', label: 'GitHub 仓库' },
|
||||
{ value: 'local', label: '本地文件系统' },
|
||||
{ value: 'eagle', label: 'Eagle 素材库' },
|
||||
]
|
||||
|
||||
export const STORAGE_PROVIDER_FIELD_DEFINITIONS: Record<
|
||||
@@ -120,57 +118,4 @@ export const STORAGE_PROVIDER_FIELD_DEFINITIONS: Record<
|
||||
helper: '使用自定义域名则可填写 false。',
|
||||
},
|
||||
],
|
||||
local: [
|
||||
{
|
||||
key: 'basePath',
|
||||
label: '基础路径',
|
||||
placeholder: './apps/web/public/photos',
|
||||
description: '本地素材所在的绝对或相对路径。',
|
||||
},
|
||||
{
|
||||
key: 'baseUrl',
|
||||
label: '访问 URL',
|
||||
placeholder: '/photos',
|
||||
description: '用于生成公开访问链接的基础 URL。',
|
||||
},
|
||||
{
|
||||
key: 'distPath',
|
||||
label: '输出目录',
|
||||
placeholder: './dist/photos',
|
||||
description: '可选,构建时复制素材到的目标目录。',
|
||||
},
|
||||
{
|
||||
key: 'excludeRegex',
|
||||
label: '排除规则 (正则)',
|
||||
placeholder: '\\.(tmp|bak)$',
|
||||
description: '可选,排除不需要复制的文件。',
|
||||
multiline: true,
|
||||
},
|
||||
{
|
||||
key: 'maxFileLimit',
|
||||
label: '最大文件数量',
|
||||
placeholder: '1000',
|
||||
description: '可选,限制扫描时的最大文件数量。',
|
||||
},
|
||||
],
|
||||
eagle: [
|
||||
{
|
||||
key: 'libraryPath',
|
||||
label: 'Eagle Library 路径',
|
||||
placeholder: '/Users/you/Library/Application Support/Eagle',
|
||||
description: 'Eagle 应用素材库的安装路径。',
|
||||
},
|
||||
{
|
||||
key: 'distPath',
|
||||
label: '输出目录',
|
||||
placeholder: './apps/web/public/originals',
|
||||
description: '可选,原图导出的目标目录。',
|
||||
},
|
||||
{
|
||||
key: 'baseUrl',
|
||||
label: '访问 URL',
|
||||
placeholder: '/originals',
|
||||
description: '用于公开访问原图的基础 URL。',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type StorageProviderType = 's3' | 'github' | 'local' | 'eagle'
|
||||
export type StorageProviderType = 's3' | 'github'
|
||||
|
||||
export interface StorageProvider {
|
||||
id: string
|
||||
|
||||
@@ -26,7 +26,7 @@ function coerceProvider(input: unknown): StorageProvider | null {
|
||||
}
|
||||
|
||||
const record = input as Record<string, unknown>
|
||||
const type = isStorageProviderType(record.type) ? record.type : 'local'
|
||||
const type = isStorageProviderType(record.type) ? record.type : 's3'
|
||||
const configInput =
|
||||
record.config && typeof record.config === 'object' && !Array.isArray(record.config)
|
||||
? (record.config as Record<string, unknown>)
|
||||
|
||||
@@ -15,32 +15,32 @@ const rootIgnores = globalIgnores([
|
||||
])
|
||||
|
||||
const hyobanConfig = await defineConfig(
|
||||
{
|
||||
formatting: false,
|
||||
lessOpinionated: true,
|
||||
preferESM: false,
|
||||
react: true,
|
||||
tailwindCSS: true,
|
||||
{
|
||||
formatting: false,
|
||||
lessOpinionated: true,
|
||||
preferESM: false,
|
||||
react: true,
|
||||
tailwindCSS: true,
|
||||
},
|
||||
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
emitDecoratorMetadata: true,
|
||||
experimentalDecorators: true,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
emitDecoratorMetadata: true,
|
||||
experimentalDecorators: true,
|
||||
},
|
||||
// TailwindCSS v4 usually has no config file. Silence the plugin's
|
||||
// config resolution warning by explicitly disabling auto-resolution.
|
||||
settings: {
|
||||
tailwindcss: {
|
||||
// ESLint plugin will not attempt to resolve tailwind config
|
||||
// which avoids repeated "Cannot resolve default tailwindcss config path" warnings.
|
||||
config: false,
|
||||
},
|
||||
|
||||
// TailwindCSS v4 usually has no config file. Silence the plugin's
|
||||
// config resolution warning by explicitly disabling auto-resolution.
|
||||
settings: {
|
||||
tailwindcss: {
|
||||
// ESLint plugin will not attempt to resolve tailwind config
|
||||
// which avoids repeated "Cannot resolve default tailwindcss config path" warnings.
|
||||
config: false,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/triple-slash-reference': 0,
|
||||
'unicorn/prefer-math-trunc': 'off',
|
||||
'unicorn/no-static-only-class': 'off',
|
||||
@@ -80,44 +80,39 @@ const hyobanConfig = await defineConfig(
|
||||
'You can use `useLocaltion` or `getReadonlyRoute` to get the route info.',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// @ts-expect-error
|
||||
{
|
||||
files: ['locales/**/*.json'],
|
||||
plugins: {
|
||||
'recursive-sort': recursiveSort,
|
||||
'check-i18n-json': checkI18nJson,
|
||||
},
|
||||
rules: {
|
||||
'recursive-sort/recursive-sort': 'error',
|
||||
'check-i18n-json/valid-i18n-keys': 'error',
|
||||
'check-i18n-json/no-extra-keys': 'error',
|
||||
},
|
||||
// @ts-expect-error
|
||||
{
|
||||
files: ['locales/**/*.json'],
|
||||
plugins: {
|
||||
'recursive-sort': recursiveSort,
|
||||
'check-i18n-json': checkI18nJson,
|
||||
},
|
||||
{
|
||||
files: ['**/*.tsx'],
|
||||
rules: {
|
||||
'@stylistic/jsx-self-closing-comp': 'error',
|
||||
},
|
||||
rules: {
|
||||
'recursive-sort/recursive-sort': 'error',
|
||||
'check-i18n-json/valid-i18n-keys': 'error',
|
||||
'check-i18n-json/no-extra-keys': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.tsx'],
|
||||
rules: {
|
||||
'@stylistic/jsx-self-closing-comp': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// Backend framework isn't React — disable React-specific hooks rule there.
|
||||
{
|
||||
files: ['be/packages/framework/**/*.{ts,tsx}'],
|
||||
rules: {
|
||||
'react-hooks/rules-of-hooks': 'off',
|
||||
},
|
||||
// Backend framework isn't React — disable React-specific hooks rule there.
|
||||
{
|
||||
files: ['be/packages/framework/**/*.{ts,tsx}'],
|
||||
rules: {
|
||||
'react-hooks/rules-of-hooks': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// Redundant but harmless: keep a local ignore in case this block is used standalone somewhere
|
||||
globalIgnores([
|
||||
'apps/ssr/src/index.html.ts',
|
||||
'apps/ssr/public/**',
|
||||
'apps/web/public/**',
|
||||
'packages/docs/public/**',
|
||||
]),
|
||||
// Redundant but harmless: keep a local ignore in case this block is used standalone somewhere
|
||||
globalIgnores(['apps/ssr/src/index.html.ts', 'apps/ssr/public/**', 'apps/web/public/**', 'packages/docs/public/**']),
|
||||
)
|
||||
|
||||
export default [
|
||||
|
||||
Reference in New Issue
Block a user