simple, clean application directory resolution
Application directory resolution for Node.js applications
Simple, clean application directory resolution for Node.js applications.
npm install appstash- Simple API: Just one function to get all your app directories
- Clean structure:
~/.<tool>/{config,cache,data,logs}+/tmp/<tool> - Graceful fallback: XDG directories → tmp if home fails
- No throws: Always returns valid paths, never throws errors
- TypeScript: Full type definitions included
- Zero dependencies: Pure Node.js implementation
import { appstash } from 'appstash';
// Get directories for your tool
const dirs = appstash('pgpm');
console.log(dirs.config); // ~/.pgpm/config
console.log(dirs.cache); // ~/.pgpm/cache
console.log(dirs.data); // ~/.pgpm/data
console.log(dirs.logs); // ~/.pgpm/logs
console.log(dirs.tmp); // /tmp/pgpmimport { appstash } from 'appstash';
// Get directories and create them
const dirs = appstash('pgpm', { ensure: true });
// All directories now exist
// dirs.usedFallback will be true if XDG or tmp fallback was usedimport { appstash, resolve } from 'appstash';
const dirs = appstash('pgpm');
// Resolve paths within directories
const configFile = resolve(dirs, 'config', 'settings.json');
// Returns: ~/.pgpm/config/settings.json
const cacheDir = resolve(dirs, 'cache', 'repos', 'my-repo');
// Returns: ~/.pgpm/cache/repos/my-repoimport { appstash, ensure } from 'appstash';
const dirs = appstash('pgpm');
// Create directories later
const result = ensure(dirs);
console.log(result.created); // ['~/.pgpm', '~/.pgpm/config', ...]
console.log(result.usedFallback); // false (or true if fallback was used)Get application directories for a tool.
Parameters:
tool(string): Tool name (e.g., 'pgpm', 'lql')options(object, optional):baseDir(string): Base directory (defaults toos.homedir())useXdgFallback(boolean): Use XDG fallback if home fails (default:true)ensure(boolean): Automatically create directories (default:false)tmpRoot(string): Root for temp directory (defaults toos.tmpdir())
Returns: AppStashResult
{
root: string; // ~/.<tool>
config: string; // ~/.<tool>/config
cache: string; // ~/.<tool>/cache
data: string; // ~/.<tool>/data
logs: string; // ~/.<tool>/logs
tmp: string; // /tmp/<tool>
usedFallback?: boolean; // true if XDG or tmp fallback was used
}Create directories if they don't exist. Never throws.
Parameters:
dirs(AppStashResult): Directory paths fromappstash()
Returns: EnsureResult
{
created: string[]; // Directories that were created
usedFallback: boolean; // true if XDG or tmp fallback was used
}Resolve a path within a specific directory.
Parameters:
dirs(AppStashResult): Directory paths fromappstash()kind('config' | 'cache' | 'data' | 'logs' | 'tmp'): Directory kindparts(string[]): Path parts to join
Returns: string - Resolved path
~/.<tool>/
├── config/ # Configuration files
├── cache/ # Cached data
├── data/ # Application data
└── logs/ # Log files
/tmp/<tool>/ # Temporary files
If home directory is unavailable or creation fails, falls back to XDG:
~/.config/<tool>/ # Config
~/.cache/<tool>/ # Cache
~/.local/share/<tool>/ # Data
~/.local/state/<tool>/logs/ # Logs
If XDG also fails, falls back to system temp:
/tmp/<tool>/
├── config/
├── cache/
├── data/
└── logs/
import { appstash, resolve } from 'appstash';
import fs from 'fs';
const dirs = appstash('myapp', { ensure: true });
const configPath = resolve(dirs, 'config', 'settings.json');
// Write config
fs.writeFileSync(configPath, JSON.stringify({ theme: 'dark' }));
// Read config
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));import { appstash, resolve } from 'appstash';
import fs from 'fs';
const dirs = appstash('myapp', { ensure: true });
const cacheFile = resolve(dirs, 'cache', 'data.json');
// Check if cached
if (fs.existsSync(cacheFile)) {
const cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
console.log('Using cached data:', cached);
} else {
// Fetch and cache
const data = await fetchData();
fs.writeFileSync(cacheFile, JSON.stringify(data));
}import { appstash, resolve } from 'appstash';
import fs from 'fs';
const dirs = appstash('myapp', { ensure: true });
const logFile = resolve(dirs, 'logs', 'app.log');
function log(message: string) {
const timestamp = new Date().toISOString();
fs.appendFileSync(logFile, `[${timestamp}] ${message}\n`);
}
log('Application started');import { appstash } from 'appstash';
// Use a custom base directory
const dirs = appstash('myapp', {
baseDir: '/opt/myapp',
ensure: true
});
console.log(dirs.config); // /opt/myapp/.myapp/config- Simple: One function, clear structure
- Clean: No pollution of exports, minimal API surface
- Graceful: Never throws, always returns valid paths
- Fallback: XDG only as absolute fallback, not primary
- Focused: Just directory resolution, no state management