mirror of
https://github.com/navidrome/navidrome.git
synced 2025-08-10 00:52:20 +00:00
* fix(ui): update artist link rendering and improve button styles Signed-off-by: Deluan <deluan@navidrome.org> * fix(ui): Move Dev* flags before sections in export --------- Signed-off-by: Deluan <deluan@navidrome.org> Co-authored-by: Deluan <deluan@navidrome.org>
171 lines
4.5 KiB
JavaScript
171 lines
4.5 KiB
JavaScript
/**
|
|
* TOML utility functions for configuration export
|
|
*/
|
|
|
|
/**
|
|
* Separates and sorts configuration entries into regular and dev configs
|
|
* @param {Array} configEntries - Array of config objects with key and value
|
|
* @returns {Object} - Object with regularConfigs and devConfigs arrays, both sorted
|
|
*/
|
|
export const separateAndSortConfigs = (configEntries) => {
|
|
const regularConfigs = []
|
|
const devConfigs = []
|
|
|
|
configEntries?.forEach((config) => {
|
|
// Skip configFile as it's displayed separately
|
|
if (config.key === 'ConfigFile') {
|
|
return
|
|
}
|
|
|
|
if (config.key.startsWith('Dev')) {
|
|
devConfigs.push(config)
|
|
} else {
|
|
regularConfigs.push(config)
|
|
}
|
|
})
|
|
|
|
// Sort configurations alphabetically
|
|
regularConfigs.sort((a, b) => a.key.localeCompare(b.key))
|
|
devConfigs.sort((a, b) => a.key.localeCompare(b.key))
|
|
|
|
return { regularConfigs, devConfigs }
|
|
}
|
|
|
|
/**
|
|
* Converts a value to proper TOML format
|
|
* @param {*} value - The value to format
|
|
* @returns {string} - The TOML-formatted value
|
|
*/
|
|
export const formatTomlValue = (value) => {
|
|
if (value === null || value === undefined) {
|
|
return '""'
|
|
}
|
|
|
|
const str = String(value)
|
|
|
|
// Boolean values
|
|
if (str === 'true' || str === 'false') {
|
|
return str
|
|
}
|
|
|
|
// Numbers (integers and floats)
|
|
if (/^-?\d+$/.test(str)) {
|
|
return str // Integer
|
|
}
|
|
if (/^-?\d*\.\d+$/.test(str)) {
|
|
return str // Float
|
|
}
|
|
|
|
// Duration values (like "300ms", "1s", "5m")
|
|
if (/^\d+(\.\d+)?(ns|us|µs|ms|s|m|h)$/.test(str)) {
|
|
return `"${str}"`
|
|
}
|
|
|
|
// Arrays/JSON objects
|
|
if (str.startsWith('[') || str.startsWith('{')) {
|
|
try {
|
|
JSON.parse(str)
|
|
return `"""${str}"""`
|
|
} catch {
|
|
return `"${str.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
|
|
}
|
|
}
|
|
|
|
// String values (escape backslashes and quotes)
|
|
return `"${str.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
|
|
}
|
|
|
|
/**
|
|
* Converts nested keys to TOML sections
|
|
* @param {Array} configs - Array of config objects with key and value
|
|
* @returns {Object} - Object with sections and rootKeys
|
|
*/
|
|
export const buildTomlSections = (configs) => {
|
|
const sections = {}
|
|
const rootKeys = []
|
|
|
|
configs.forEach(({ key, value }) => {
|
|
if (key.includes('.')) {
|
|
const parts = key.split('.')
|
|
const sectionName = parts[0]
|
|
const keyName = parts.slice(1).join('.')
|
|
|
|
if (!sections[sectionName]) {
|
|
sections[sectionName] = []
|
|
}
|
|
sections[sectionName].push({ key: keyName, value })
|
|
} else {
|
|
rootKeys.push({ key, value })
|
|
}
|
|
})
|
|
|
|
return { sections, rootKeys }
|
|
}
|
|
|
|
/**
|
|
* Converts configuration data to TOML format
|
|
* @param {Object} configData - The configuration data object
|
|
* @param {Function} translate - Translation function for internationalization
|
|
* @returns {string} - The TOML-formatted configuration
|
|
*/
|
|
export const configToToml = (configData, translate = (key) => key) => {
|
|
let tomlContent = `# Navidrome Configuration\n# Generated on ${new Date().toISOString()}\n\n`
|
|
|
|
const { regularConfigs, devConfigs } = separateAndSortConfigs(
|
|
configData.config,
|
|
)
|
|
|
|
// Process regular configs
|
|
const { sections: regularSections, rootKeys: regularRootKeys } =
|
|
buildTomlSections(regularConfigs)
|
|
|
|
// Add root-level keys first
|
|
if (regularRootKeys.length > 0) {
|
|
regularRootKeys.forEach(({ key, value }) => {
|
|
tomlContent += `${key} = ${formatTomlValue(value)}\n`
|
|
})
|
|
tomlContent += '\n'
|
|
}
|
|
|
|
// Add dev configs if any
|
|
if (devConfigs.length > 0) {
|
|
tomlContent += `# ${translate('about.config.devFlagsHeader')}\n`
|
|
tomlContent += `# ${translate('about.config.devFlagsComment')}\n\n`
|
|
|
|
const { sections: devSections, rootKeys: devRootKeys } =
|
|
buildTomlSections(devConfigs)
|
|
|
|
// Add dev root-level keys
|
|
devRootKeys.forEach(({ key, value }) => {
|
|
tomlContent += `${key} = ${formatTomlValue(value)}\n`
|
|
})
|
|
if (devRootKeys.length > 0) {
|
|
tomlContent += '\n'
|
|
}
|
|
|
|
// Add dev sections
|
|
Object.keys(devSections)
|
|
.sort()
|
|
.forEach((sectionName) => {
|
|
tomlContent += `[${sectionName}]\n`
|
|
devSections[sectionName].forEach(({ key, value }) => {
|
|
tomlContent += `${key} = ${formatTomlValue(value)}\n`
|
|
})
|
|
tomlContent += '\n'
|
|
})
|
|
}
|
|
|
|
// Add sections
|
|
Object.keys(regularSections)
|
|
.sort()
|
|
.forEach((sectionName) => {
|
|
tomlContent += `[${sectionName}]\n`
|
|
regularSections[sectionName].forEach(({ key, value }) => {
|
|
tomlContent += `${key} = ${formatTomlValue(value)}\n`
|
|
})
|
|
tomlContent += '\n'
|
|
})
|
|
|
|
return tomlContent
|
|
}
|