mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-08 02:11:35 +00:00
55 lines
1.6 KiB
JavaScript
55 lines
1.6 KiB
JavaScript
// server/utils/userProgressStore.js
|
||
const Path = require('path')
|
||
const fsx = require('../libs/fsExtra')
|
||
|
||
function dir () {
|
||
// Persist under MetadataPath so it survives restarts/backups similar to other ABS data
|
||
const root = global.MetadataPath || Path.join(process.cwd(), '.metadata')
|
||
const p = Path.join(root, 'achievements')
|
||
if (!fsx.pathExistsSync(p)) fsx.mkdirpSync(p)
|
||
return p
|
||
}
|
||
|
||
function file (userId) {
|
||
return Path.join(dir(), `${userId}.json`)
|
||
}
|
||
|
||
async function read (userId) {
|
||
const f = file(userId)
|
||
if (!fsx.pathExistsSync(f)) return null
|
||
try {
|
||
return JSON.parse(await fsx.readFile(f, 'utf8'))
|
||
} catch {
|
||
return null
|
||
}
|
||
}
|
||
|
||
async function write (userId, data) {
|
||
const f = file(userId)
|
||
const payload = JSON.stringify(data, null, 2)
|
||
|
||
// Your fs-extra wrapper doesn’t expose writeFileAtomic.
|
||
// Use a safe fallback; prefer atomic (tmp + rename) when possible.
|
||
try {
|
||
if (typeof fsx.writeFileAtomic === 'function') {
|
||
await fsx.writeFileAtomic(f, payload, 'utf8')
|
||
} else {
|
||
const tmp = f + '.tmp'
|
||
await fsx.writeFile(tmp, payload, 'utf8')
|
||
// Some wrappers expose rename, some move; fall back to writeFile
|
||
if (typeof fsx.rename === 'function') {
|
||
await fsx.rename(tmp, f)
|
||
} else if (typeof fsx.move === 'function') {
|
||
await fsx.move(tmp, f, { overwrite: true })
|
||
} else {
|
||
// last-resort non-atomic
|
||
await fsx.writeFile(f, payload, 'utf8')
|
||
}
|
||
}
|
||
} catch {
|
||
// Non-atomic final fallback to guarantee progress is saved
|
||
await fsx.writeFile(f, payload, 'utf8')
|
||
}
|
||
}
|
||
|
||
module.exports = { read, write }
|