186 lines
4.3 KiB
JavaScript
186 lines
4.3 KiB
JavaScript
const { PrismaClient } = require('@prisma/client')
|
||
|
||
const prisma = new PrismaClient()
|
||
|
||
function isArrayString(str) {
|
||
const trimmed = (str || '').trim()
|
||
if (!trimmed.startsWith('[') || !trimmed.endsWith(']')) return false
|
||
try {
|
||
const parsed = JSON.parse(trimmed)
|
||
return Array.isArray(parsed)
|
||
} catch {
|
||
return false
|
||
}
|
||
}
|
||
|
||
function normalizeOptionValue(option) {
|
||
let cleaned = (option || '').trim()
|
||
if (!cleaned) return ''
|
||
|
||
try {
|
||
if (
|
||
(cleaned.startsWith('"') && cleaned.endsWith('"')) ||
|
||
(cleaned.startsWith("'") && cleaned.endsWith("'"))
|
||
) {
|
||
const parsed = JSON.parse(cleaned)
|
||
if (typeof parsed === 'string') {
|
||
cleaned = parsed.trim()
|
||
}
|
||
}
|
||
} catch {
|
||
// ignore parse errors
|
||
}
|
||
|
||
cleaned = cleaned.replace(/\\+"/g, '"').replace(/\\'/g, "'")
|
||
cleaned = cleaned.replace(/["'`“”]/g, '')
|
||
cleaned = cleaned.trim()
|
||
if (cleaned.startsWith('\\') && cleaned.endsWith('\\')) {
|
||
cleaned = cleaned.slice(1, -1).trim()
|
||
}
|
||
return cleaned.trim()
|
||
}
|
||
|
||
function stripLooseBrackets(value) {
|
||
let result = (value || '').trim()
|
||
let guard = 0
|
||
while (result.startsWith('[') && result.endsWith(']') && guard < 5) {
|
||
const inner = result.slice(1, -1).trim()
|
||
if (!inner || inner === result) {
|
||
break
|
||
}
|
||
result = inner
|
||
guard += 1
|
||
}
|
||
return result
|
||
}
|
||
|
||
function extractLooseArrayOptions(option) {
|
||
let trimmed = (option || '').trim()
|
||
if (!trimmed.startsWith('[') || !trimmed.endsWith(']')) return null
|
||
|
||
let inner = trimmed
|
||
let safeGuard = 0
|
||
while (inner.startsWith('[') && inner.endsWith(']') && safeGuard < 5) {
|
||
const next = inner.slice(1, -1).trim()
|
||
if (!next || next === inner) {
|
||
break
|
||
}
|
||
inner = next
|
||
safeGuard += 1
|
||
}
|
||
|
||
if (!inner) return []
|
||
|
||
const segments = inner.split(/[,,]/).map(seg => normalizeOptionValue(seg)).filter(Boolean)
|
||
if (segments.length > 1) {
|
||
return segments
|
||
}
|
||
|
||
const single = normalizeOptionValue(inner)
|
||
return single ? [single] : null
|
||
}
|
||
|
||
function sanitizeOptions(optionsStatic) {
|
||
if (!optionsStatic) return []
|
||
|
||
const result = new Set()
|
||
const pushOption = (value) => {
|
||
const normalized = stripLooseBrackets(normalizeOptionValue(value))
|
||
if (normalized && !isArrayString(normalized)) {
|
||
result.add(normalized)
|
||
}
|
||
}
|
||
|
||
try {
|
||
const parsed = JSON.parse(optionsStatic)
|
||
if (Array.isArray(parsed)) {
|
||
parsed.forEach(opt => {
|
||
const optStr = String(opt || '').trim()
|
||
if (!optStr) return
|
||
|
||
const loose = extractLooseArrayOptions(optStr)
|
||
if (loose && loose.length) {
|
||
loose.forEach(pushOption)
|
||
return
|
||
}
|
||
|
||
if (isArrayString(optStr)) {
|
||
try {
|
||
const nested = JSON.parse(optStr)
|
||
if (Array.isArray(nested)) {
|
||
nested.forEach(item => pushOption(String(item)))
|
||
return
|
||
}
|
||
} catch {
|
||
// ignore
|
||
}
|
||
}
|
||
|
||
pushOption(optStr)
|
||
})
|
||
return Array.from(result)
|
||
}
|
||
} catch {
|
||
// ignored
|
||
}
|
||
|
||
optionsStatic
|
||
.split('\n')
|
||
.map(line => line.trim())
|
||
.filter(Boolean)
|
||
.forEach(line => {
|
||
const loose = extractLooseArrayOptions(line)
|
||
if (loose && loose.length) {
|
||
loose.forEach(pushOption)
|
||
} else {
|
||
pushOption(line)
|
||
}
|
||
})
|
||
|
||
return Array.from(result)
|
||
}
|
||
|
||
async function main() {
|
||
const fields = await prisma.uploadField.findMany({
|
||
where: {
|
||
optionsStatic: {
|
||
not: null,
|
||
},
|
||
},
|
||
select: {
|
||
id: true,
|
||
key: true,
|
||
label: true,
|
||
optionsStatic: true,
|
||
},
|
||
})
|
||
|
||
let updated = 0
|
||
for (const field of fields) {
|
||
const sanitized = sanitizeOptions(field.optionsStatic)
|
||
const sanitizedJson = JSON.stringify(sanitized)
|
||
const currentTrimmed = (field.optionsStatic || '').trim()
|
||
|
||
if (sanitizedJson && sanitizedJson !== currentTrimmed) {
|
||
await prisma.uploadField.update({
|
||
where: { id: field.id },
|
||
data: { optionsStatic: sanitizedJson },
|
||
})
|
||
updated += 1
|
||
console.log(`[Cleanup] Updated ${field.key} (${field.label}) -> ${sanitizedJson}`)
|
||
}
|
||
}
|
||
|
||
console.log(`Cleanup finished. Updated ${updated} field(s).`)
|
||
}
|
||
|
||
main()
|
||
.catch((error) => {
|
||
console.error('Cleanup failed:', error)
|
||
process.exitCode = 1
|
||
})
|
||
.finally(async () => {
|
||
await prisma.$disconnect()
|
||
})
|
||
|