persist-read.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /**
  2. * 持久化读取:从当前流程目录 save/config.json 按 key 读取(与 persist-save 成对,仅 string / number)
  3. */
  4. const path = require('path')
  5. const fs = require('fs')
  6. /** 确保 save 目录存在;若无 config.json 则写入 {} */
  7. function ensurePersistConfigFile (configPath) {
  8. const saveDir = path.dirname(configPath)
  9. try {
  10. if (!fs.existsSync(saveDir)) {
  11. fs.mkdirSync(saveDir, { recursive: true })
  12. }
  13. if (!fs.existsSync(configPath)) {
  14. fs.writeFileSync(configPath, '{}\n', 'utf8')
  15. }
  16. } catch (e) {
  17. return { ok: false, error: `persist-read 无法创建 save/config: ${e.message || e}` }
  18. }
  19. return { ok: true }
  20. }
  21. function isAllowedPersistValue (val) {
  22. if (val === null || val === undefined) return { ok: false, error: 'persist-read 不支持 null / undefined' }
  23. if (typeof val === 'string' || typeof val === 'number') {
  24. if (typeof val === 'number' && !Number.isFinite(val)) {
  25. return { ok: false, error: 'persist-read 不支持 NaN / Infinity' }
  26. }
  27. return { ok: true }
  28. }
  29. if (typeof val === 'boolean') {
  30. return { ok: false, error: 'persist-read 仅支持读取 string 与 number,当前为 boolean' }
  31. }
  32. return { ok: false, error: 'persist-read 仅支持读取 string 与 number,不支持 object/array' }
  33. }
  34. async function executePersistRead ({ stateKey, folderPath }) {
  35. if (!folderPath || typeof folderPath !== 'string') {
  36. return { success: false, error: 'persist-read 缺少流程目录 folderPath' }
  37. }
  38. if (stateKey == null || String(stateKey).trim() === '') {
  39. return { success: false, error: 'persist-read 缺少 key(JSON 键名)' }
  40. }
  41. const key = String(stateKey).trim()
  42. const configPath = path.join(folderPath, 'save', 'config.json')
  43. const ensured = ensurePersistConfigFile(configPath)
  44. if (!ensured.ok) {
  45. return { success: false, error: ensured.error }
  46. }
  47. let data
  48. try {
  49. const raw = fs.readFileSync(configPath, 'utf8')
  50. data = JSON.parse(raw)
  51. } catch (e) {
  52. return { success: false, error: `persist-read 解析 config.json 失败: ${e.message || e}` }
  53. }
  54. if (!data || typeof data !== 'object' || Array.isArray(data)) {
  55. return { success: false, error: 'persist-read config.json 必须为 JSON 对象' }
  56. }
  57. if (!Object.prototype.hasOwnProperty.call(data, key)) {
  58. return { success: true, value: '', result: '' }
  59. }
  60. const val = data[key]
  61. const check = isAllowedPersistValue(val)
  62. if (!check.ok) {
  63. return { success: false, error: check.error }
  64. }
  65. return { success: true, value: val, result: val }
  66. }
  67. module.exports = { executePersistRead }