refactor(linkedin-studio): M0-5 — queue-manager.mjs via getDataRoot('drafts')

This commit is contained in:
Kjell Tore Guttormsen 2026-06-18 11:31:56 +02:00
commit 7f386943c6
2 changed files with 59 additions and 4 deletions

View file

@ -0,0 +1,57 @@
import { describe, test, before, after } from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync, rmSync, existsSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
// M0-5: queue-manager must resolve its queue under the EXTERNAL data root
// (getDataRoot('drafts')), never the plugin tree. The module binds QUEUE_FILE at
// load time, so LINKEDIN_STUDIO_DATA is stubbed BEFORE the dynamic import. A
// separate PLUGIN_ROOT tempdir lets us assert the queue does NOT land in the
// plugin tree without polluting the real working tree (the old default would
// have written there).
// Pattern: data-root.test.mjs env-stub + personalization-score.test.mjs tempdir.
describe('queue-manager — external data root (M0-5)', () => {
let dataDir, pluginDir, qm;
const saved = {
LINKEDIN_STUDIO_DATA: process.env.LINKEDIN_STUDIO_DATA,
PLUGIN_ROOT: process.env.PLUGIN_ROOT,
};
before(async () => {
dataDir = mkdtempSync(join(tmpdir(), 'lis-queue-data-'));
pluginDir = mkdtempSync(join(tmpdir(), 'lis-queue-plugin-'));
process.env.LINKEDIN_STUDIO_DATA = dataDir;
process.env.PLUGIN_ROOT = pluginDir;
qm = await import('../queue-manager.mjs');
});
after(() => {
for (const d of [dataDir, pluginDir]) {
if (d && existsSync(d)) rmSync(d, { recursive: true, force: true });
}
for (const [k, v] of Object.entries(saved)) {
if (v === undefined) delete process.env[k];
else process.env[k] = v;
}
});
test('an empty queue materializes under <dataDir>/drafts/queue.json', () => {
assert.deepEqual(qm.queueRead(), []);
assert.ok(
existsSync(join(dataDir, 'drafts', 'queue.json')),
'queue file must be created under the external drafts dir',
);
});
test('queueAdd persists to the external root, never the plugin tree', () => {
qm.queueAdd('m0-5', '/tmp/draft.md', '2026-06-20', '09:00', 'ai', 'text', 'hook', 1234);
const entries = qm.queueRead();
assert.equal(entries.length, 1);
assert.equal(entries[0].id, 'm0-5');
assert.ok(
!existsSync(join(pluginDir, 'assets', 'drafts', 'queue.json')),
'queue must NOT land in the plugin tree (PLUGIN_ROOT default removed)',
);
});
});

View file

@ -5,11 +5,9 @@
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { getDataRoot } from './data-root.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const PLUGIN_ROOT = process.env.PLUGIN_ROOT || join(__dirname, '..', '..');
const QUEUE_FILE = join(PLUGIN_ROOT, 'assets', 'drafts', 'queue.json');
const QUEUE_FILE = join(getDataRoot('drafts'), 'queue.json');
function ensureQueue() {
if (!existsSync(QUEUE_FILE)) {