From 36cad815ed097426972a15b7f553ae27840dfbf0 Mon Sep 17 00:00:00 2001 From: Abhinav Dhiman Date: Tue, 19 Aug 2025 17:04:03 +0530 Subject: [PATCH 1/2] fix(settings): load config from DB if available, otherwise fallback to file or defaults - Introduced DEFAULTS as baseline Settings object - Added usability check (require publicKey, privateKey, urlEndpoint) - Use DB config if usable; else use file config; else fallback to defaults --- server/src/services/settings.service.ts | 147 +++++++++++++++--------- 1 file changed, 91 insertions(+), 56 deletions(-) diff --git a/server/src/services/settings.service.ts b/server/src/services/settings.service.ts index b6afba5..00d1cc0 100644 --- a/server/src/services/settings.service.ts +++ b/server/src/services/settings.service.ts @@ -2,77 +2,112 @@ import { Core } from '@strapi/strapi'; import { PLUGIN_ID, Settings } from '../../../common'; import { clearImageKitClient } from './upload.service'; +const DEFAULTS: Settings = { + enabled: false, + publicKey: '', + privateKey: '', + urlEndpoint: '', + useSignedUrls: false, + uploadEnabled: false, + expiry: 0, + uploadOptions: { + tags: [], + folder: '', + overwriteTags: false, + overwriteCustomMetadata: false, + checks: '', + isPrivateFile: false, + }, +}; + +function isNonEmptyString(v: unknown): boolean { + return typeof v === 'string' && v.trim().length > 0; +} + +function isConfigUsable(config: Partial | undefined): boolean { + if (!config) return false; + return ( + isNonEmptyString(config.publicKey) && + isNonEmptyString(config.urlEndpoint) && + isNonEmptyString(config.privateKey) + ); +} + +/** Shallow merge defaults with candidate, returning full Settings */ +function fillWithDefaults(candidate: Partial | undefined): Settings { + return { + ...DEFAULTS, + ...candidate, + uploadOptions: { + ...DEFAULTS.uploadOptions, + ...(candidate?.uploadOptions ?? {}), + }, + }; +} + const settingsService = ({ strapi }: { strapi: Core.Strapi }) => { function getPluginStore() { - if (strapi.store) { - return strapi.store({ type: 'plugin', name: PLUGIN_ID }); - } + return strapi.store + ? strapi.store({ type: 'plugin', name: PLUGIN_ID }) + : { get: async () => DEFAULTS, set: async () => {}, delete: async () => {} }; + } + + function getConfigFromFile(): Partial { + const plugin = strapi.plugin(PLUGIN_ID); return { - get: async () => { - return { - enabled: false, - publicKey: '', - privateKey: '', - urlEndpoint: '', - useSignedUrls: false, - uploadEnabled: false, - expiry: 0, - uploadOptions: { - tags: [], - folder: '', - overwriteTags: false, - overwriteCustomMetadata: false, - checks: '', - isPrivateFile: false, - }, - useTransformUrls: false, - }; + enabled: plugin.config('enabled'), + publicKey: plugin.config('publicKey'), + privateKey: plugin.config('privateKey'), + urlEndpoint: plugin.config('urlEndpoint'), + useSignedUrls: plugin.config('useSignedUrls'), + uploadEnabled: plugin.config('uploadEnabled'), + expiry: plugin.config('expiry'), + uploadOptions: { + tags: plugin.config('uploadOptions.tags'), + folder: plugin.config('uploadOptions.folder'), + overwriteTags: plugin.config('uploadOptions.overwriteTags'), + overwriteCustomMetadata: plugin.config('uploadOptions.overwriteCustomMetadata'), + checks: plugin.config('uploadOptions.checks'), + isPrivateFile: plugin.config('uploadOptions.isPrivateFile'), }, - set: async () => {}, - delete: async () => {}, }; } + async function getConfigFromDb(): Promise | undefined> { + try { + return (await getPluginStore().get({ key: 'config' })) as Partial; + } catch { + return undefined; + } + } + async function getSettings(): Promise { - const pluginStore = getPluginStore(); - const config = (await pluginStore.get({ key: 'config' })) as Settings; - return config; + const dbCfg = await getConfigFromDb(); + if (isConfigUsable(dbCfg)) { + return fillWithDefaults(dbCfg); + } + + const fileCfg = getConfigFromFile(); + if (isConfigUsable(fileCfg)) { + return fillWithDefaults(fileCfg); + } + + return DEFAULTS; } async function updateSettings(settings: Settings): Promise { - const pluginStore = getPluginStore(); - await pluginStore.set({ key: 'config', value: settings }); + const store = getPluginStore(); + await store.set({ key: 'config', value: settings }); clearImageKitClient(); - return await getSettings(); - } - - function getLocalConfig(): Settings { - const plugin = strapi.plugin(PLUGIN_ID); - return { - enabled: plugin.config('enabled', false), - publicKey: plugin.config('publicKey', ''), - privateKey: plugin.config('privateKey', ''), - urlEndpoint: plugin.config('urlEndpoint', ''), - useSignedUrls: plugin.config('useSignedUrls', false), - uploadEnabled: plugin.config('uploadEnabled', false), - expiry: plugin.config('expiry', 0), - uploadOptions: { - tags: plugin.config('uploadOptions.tags', []), - folder: plugin.config('uploadOptions.folder', ''), - overwriteTags: plugin.config('uploadOptions.overwriteTags', false), - overwriteCustomMetadata: plugin.config( - 'uploadOptions.overwriteCustomMetadata', - false - ), - checks: plugin.config('uploadOptions.checks', ''), - isPrivateFile: plugin.config('uploadOptions.isPrivateFile', false), - }, - }; + return getSettings(); } async function restoreConfig(): Promise { - await updateSettings(getLocalConfig()); - return await getSettings(); + const fileCfg = getConfigFromFile(); + const store = getPluginStore(); + await store.set({ key: 'config', value: fillWithDefaults(fileCfg) }); + clearImageKitClient(); + return getSettings(); } return { getSettings, updateSettings, restoreConfig }; From 253689da8b8406bcb62d085bc4e9204094a07079 Mon Sep 17 00:00:00 2001 From: Abhinav Dhiman Date: Tue, 19 Aug 2025 20:32:04 +0530 Subject: [PATCH 2/2] release: bump version from 1.0.1 to 1.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2fa021..9083a1e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.0.1", + "version": "1.0.2", "keywords": [], "type": "commonjs", "exports": {