From 57c9642a98c3d39ef9aba495ba4b5f13408964ac Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 2 Nov 2025 20:46:33 +0800 Subject: [PATCH] refactor(storage-providers): streamline provider handling and remove unused types Signed-off-by: Innei --- .../src/modules/setting/setting.service.ts | 17 ++- .../components/ProviderCard.tsx | 7 +- .../components/StorageProvidersManager.tsx | 4 +- .../modules/storage-providers/constants.ts | 57 +--------- .../src/modules/storage-providers/types.ts | 2 +- .../src/modules/storage-providers/utils.ts | 2 +- eslint.config.mjs | 103 +++++++++--------- 7 files changed, 69 insertions(+), 123 deletions(-) diff --git a/be/apps/core/src/modules/setting/setting.service.ts b/be/apps/core/src/modules/setting/setting.service.ts index 2dd69bd6..a5aa8556 100644 --- a/be/apps/core/src/modules/setting/setting.service.ts +++ b/be/apps/core/src/modules/setting/setting.service.ts @@ -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(key: K, value: SettingValueMap[K], options: SetSettingOptions): Promise diff --git a/be/apps/dashboard/src/modules/storage-providers/components/ProviderCard.tsx b/be/apps/dashboard/src/modules/storage-providers/components/ProviderCard.tsx index e0dfe866..3710597e 100644 --- a/be/apps/dashboard/src/modules/storage-providers/components/ProviderCard.tsx +++ b/be/apps/dashboard/src/modules/storage-providers/components/ProviderCard.tsx @@ -58,12 +58,7 @@ export const ProviderCard: FC = ({ 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' } diff --git a/be/apps/dashboard/src/modules/storage-providers/components/StorageProvidersManager.tsx b/be/apps/dashboard/src/modules/storage-providers/components/StorageProvidersManager.tsx index 81719e4d..518a5a72 100644 --- a/be/apps/dashboard/src/modules/storage-providers/components/StorageProvidersManager.tsx +++ b/be/apps/dashboard/src/modules/storage-providers/components/StorageProvidersManager.tsx @@ -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 diff --git a/be/apps/dashboard/src/modules/storage-providers/constants.ts b/be/apps/dashboard/src/modules/storage-providers/constants.ts index 09361778..762d439a 100644 --- a/be/apps/dashboard/src/modules/storage-providers/constants.ts +++ b/be/apps/dashboard/src/modules/storage-providers/constants.ts @@ -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。', - }, - ], } diff --git a/be/apps/dashboard/src/modules/storage-providers/types.ts b/be/apps/dashboard/src/modules/storage-providers/types.ts index 9572f02a..ea29902d 100644 --- a/be/apps/dashboard/src/modules/storage-providers/types.ts +++ b/be/apps/dashboard/src/modules/storage-providers/types.ts @@ -1,4 +1,4 @@ -export type StorageProviderType = 's3' | 'github' | 'local' | 'eagle' +export type StorageProviderType = 's3' | 'github' export interface StorageProvider { id: string diff --git a/be/apps/dashboard/src/modules/storage-providers/utils.ts b/be/apps/dashboard/src/modules/storage-providers/utils.ts index 569febf3..2e2c38f8 100644 --- a/be/apps/dashboard/src/modules/storage-providers/utils.ts +++ b/be/apps/dashboard/src/modules/storage-providers/utils.ts @@ -26,7 +26,7 @@ function coerceProvider(input: unknown): StorageProvider | null { } const record = input as Record - 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) diff --git a/eslint.config.mjs b/eslint.config.mjs index e58a8e4a..5e727c9b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -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 [