diff --git a/src/core/json-state-store.mjs b/src/core/json-state-store.mjs index c688559..272e784 100644 --- a/src/core/json-state-store.mjs +++ b/src/core/json-state-store.mjs @@ -28,8 +28,9 @@ export function createJsonStateStore({ stateDir, fileName, initialState = {} }) } function replaceState(target, nextState) { + const source = nextState === target ? structuredClone(nextState) : (nextState || {}); for (const key of Object.keys(target)) delete target[key]; - Object.assign(target, nextState || {}); + Object.assign(target, source); } function loadState(filePath, initialState) { diff --git a/test/json-state-store.test.mjs b/test/json-state-store.test.mjs new file mode 100644 index 0000000..542134c --- /dev/null +++ b/test/json-state-store.test.mjs @@ -0,0 +1,54 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; + +import { createJsonStateStore } from '../src/core/json-state-store.mjs'; + +test('json state store preserves mutated in-memory state on setState', () => { + const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), 'unrip-json-state-')); + const store = createJsonStateStore({ + stateDir, + fileName: 'state.json', + initialState: { + paused: false, + publish_count: 0, + deposit_addresses: {}, + }, + }); + + const state = store.getState(); + state.publish_count = 1; + state.deposit_addresses['btc:mainnet'] = { + address: 'bc1qexample', + }; + + store.setState(state); + + assert.deepEqual(store.getState(), { + paused: false, + publish_count: 1, + deposit_addresses: { + 'btc:mainnet': { + address: 'bc1qexample', + }, + }, + }); + + const reloaded = createJsonStateStore({ + stateDir, + fileName: 'state.json', + initialState: {}, + }); + + assert.deepEqual(reloaded.getState(), { + paused: false, + publish_count: 1, + deposit_addresses: { + 'btc:mainnet': { + address: 'bc1qexample', + }, + }, + }); +});