linkedin-studio/hooks/scripts/data-root.mjs

39 lines
1.8 KiB
JavaScript

#!/usr/bin/env node
// CANONICAL — twin of scripts/analytics/src/utils/storage.ts:getDataRoot.
// MUST STAY IN SYNC: identical default (~/.claude/linkedin-studio) + identical
// LINKEDIN_STUDIO_DATA override semantics. A twin exists (not a shared import)
// because the runtimes differ: hooks are plain .mjs run by Node with zero npm
// deps and cannot import the TypeScript module (which needs tsx). Change one →
// change the other; the twin-consistency test in __tests__/data-root.test.mjs
// guards the contract behaviorally.
import { join } from 'node:path';
import { homedir } from 'node:os';
import { fileURLToPath } from 'node:url';
// HOME with the codebase idiom (state-updater.mjs:11), but NEVER fall through to
// '' — that would turn the absolute data path into a CWD-relative one. os.homedir()
// is the floor (risk-assessor Low #2).
function resolveHome() {
return process.env.HOME || process.env.USERPROFILE || homedir();
}
// Canonical per-user data root: ~/.claude/linkedin-studio (mirrors the state-file
// location), overridable via LINKEDIN_STUDIO_DATA (test + power-user seam).
// No-arg / '' returns the root itself; a subdir returns root/subdir.
export function getDataRoot(subdir = '') {
const dataBase = process.env.LINKEDIN_STUDIO_DATA || join(resolveHome(), '.claude', 'linkedin-studio');
return subdir ? join(dataBase, subdir) : dataBase;
}
// State file lives beside the data dir (mirrors state-updater.mjs:12).
export function getStateFile() {
return process.env.STATE_FILE || join(resolveHome(), '.claude', 'linkedin-studio.local.md');
}
// Standalone: print the resolved paths for debugging (pattern: personalization-score.mjs:120).
if (process.argv[1] === fileURLToPath(import.meta.url)) {
console.log('data root:', getDataRoot());
console.log('analytics:', getDataRoot('analytics'));
console.log('state file:', getStateFile());
}