Added check for duplicate config entries

This commit is contained in:
2026-07-05 21:13:18 +01:00
parent d22f0aa316
commit 90e5df4a2d
+48
View File
@@ -42,6 +42,54 @@ function validateConfig(config) {
throw new Error('Configuration must include at least one `apiKeys` or `serviceAccounts`');
}
// Ensure API key values are unique when using apiKeys
if (hasApiKeys) {
const extracted = config.apiKeys.map(item => {
if (typeof item === 'string') return item.trim();
if (item && typeof item === 'object') return (item.key || item.apiKey || '').toString().trim();
return '';
});
const nonEmpty = extracted.filter(Boolean);
const unique = new Set(nonEmpty);
if (unique.size !== nonEmpty.length) {
throw new Error('`apiKeys` contains duplicate `key` values; ensure all API keys are unique');
}
}
// Ensure service account credential paths are unique when using serviceAccounts
if (hasSvcAccounts) {
// Read and canonicalize the contents of each service account credential
const svcContents = config.serviceAccounts.map(item => {
let p = '';
if (typeof item === 'string') p = item.trim();
else if (item && typeof item === 'object') p = (item.path || item.file || item.credentialsPath || '').toString().trim();
if (!p) return '';
const full = path.isAbsolute(p) ? p : path.resolve(process.cwd(), p);
if (!fs.existsSync(full)) {
throw new Error(`Service account file not found: ${p}`);
}
const raw = fs.readFileSync(full, 'utf8').trim();
try {
const parsed = JSON.parse(raw);
const canonicalize = (obj) => {
if (obj === null || typeof obj !== 'object') return JSON.stringify(obj);
if (Array.isArray(obj)) return '[' + obj.map(canonicalize).join(',') + ']';
const keys = Object.keys(obj).sort();
return '{' + keys.map(k => JSON.stringify(k) + ':' + canonicalize(obj[k])).join(',') + '}';
};
return canonicalize(parsed);
} catch (e) {
// Non-JSON files: use raw contents
return raw;
}
}).filter(Boolean);
const uniqueSvc = new Set(svcContents);
if (uniqueSvc.size !== svcContents.length) {
throw new Error('`serviceAccounts` contains duplicate credential contents; ensure all service account credentials are unique');
}
}
// Basic validation of documents/sheets structure
for (const doc of config.documents) {
if (!doc.documentId) throw new Error('Each document must include a `documentId`');