persist-save.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /**
  2. * 持久化保存:将单个键值写入当前流程目录 save/config.json
  3. * 支持:string、number;普通 object(如 {x,y})会 JSON.stringify 后以字符串写入
  4. * 路径:folderPath/save/config.json(folderPath 一般为 static/process/<流程名>)
  5. */
  6. const path = require('path')
  7. const fs = require('fs')
  8. function normalizeStoredValue (value) {
  9. if (value === undefined) {
  10. return { ok: false, error: 'persist-save 缺少 value' }
  11. }
  12. if (value === null) {
  13. return { ok: false, error: 'persist-save 不支持 null' }
  14. }
  15. if (typeof value === 'number') {
  16. if (!Number.isFinite(value)) {
  17. return { ok: false, error: 'persist-save 不支持 NaN / Infinity' }
  18. }
  19. return { ok: true, stored: value }
  20. }
  21. if (typeof value === 'string') {
  22. return { ok: true, stored: value }
  23. }
  24. if (typeof value === 'object') {
  25. if (Array.isArray(value)) {
  26. return { ok: false, error: 'persist-save 不支持 array' }
  27. }
  28. try {
  29. return { ok: true, stored: JSON.stringify(value) }
  30. } catch (e) {
  31. return { ok: false, error: 'persist-save 对象无法序列化为 JSON' }
  32. }
  33. }
  34. if (typeof value === 'boolean') {
  35. return { ok: false, error: 'persist-save 仅支持 string 与 number,当前为 boolean' }
  36. }
  37. return { ok: false, error: `persist-save 仅支持 string 与 number,当前类型: ${typeof value}` }
  38. }
  39. async function executePersistSave ({ stateKey, stateValue, folderPath }) {
  40. if (!folderPath || typeof folderPath !== 'string') {
  41. return { success: false, error: 'persist-save 缺少流程目录 folderPath' }
  42. }
  43. if (stateKey == null || String(stateKey).trim() === '') {
  44. return { success: false, error: 'persist-save 缺少 key(JSON 键名)' }
  45. }
  46. const key = String(stateKey).trim()
  47. const norm = normalizeStoredValue(stateValue)
  48. if (!norm.ok) {
  49. return { success: false, error: norm.error }
  50. }
  51. const saveDir = path.join(folderPath, 'save')
  52. const configPath = path.join(saveDir, 'config.json')
  53. let data = {}
  54. try {
  55. if (fs.existsSync(configPath)) {
  56. const raw = fs.readFileSync(configPath, 'utf8')
  57. const parsed = JSON.parse(raw)
  58. if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
  59. data = parsed
  60. }
  61. }
  62. } catch (_) {
  63. data = {}
  64. }
  65. data[key] = norm.stored
  66. try {
  67. fs.mkdirSync(saveDir, { recursive: true })
  68. fs.writeFileSync(configPath, JSON.stringify(data, null, 2), 'utf8')
  69. } catch (e) {
  70. return { success: false, error: `persist-save 写入失败: ${e.message || e}` }
  71. }
  72. return { success: true, path: configPath, key, value: norm.stored }
  73. }
  74. module.exports = { executePersistSave }