Files
smartnftables/ts/nft.executor.ts
2026-03-26 10:32:05 +00:00

75 lines
1.8 KiB
TypeScript

import * as plugins from './plugins.js';
const execFile = plugins.util.promisify(plugins.childProcess.execFile);
export class NftNotRootError extends Error {
constructor() {
super('Not running as root — nftables commands require root privileges');
this.name = 'NftNotRootError';
}
}
export class NftCommandError extends Error {
public readonly command: string;
public readonly stderr: string;
constructor(command: string, stderr: string) {
super(`nft command failed: ${command}${stderr}`);
this.name = 'NftCommandError';
this.command = command;
this.stderr = stderr;
}
}
/**
* Low-level executor for nft CLI commands.
*/
export class NftExecutor {
private dryRun: boolean;
constructor(options?: { dryRun?: boolean }) {
this.dryRun = options?.dryRun ?? false;
}
/** Check if running as root (euid 0). */
public isRoot(): boolean {
return process.getuid?.() === 0;
}
/**
* Execute a single nft command.
* The command may or may not start with "nft " — the prefix is stripped if present.
* Returns stdout on success.
*/
public async exec(command: string): Promise<string> {
if (this.dryRun) {
return '';
}
// Strip "nft " prefix if present
const args = command.startsWith('nft ') ? command.slice(4) : command;
const { stdout } = await execFile('nft', args.split(/\s+/));
return stdout;
}
/**
* Execute multiple nft commands sequentially.
* By default stops on first failure. Set continueOnError to keep going.
*/
public async execBatch(
commands: string[],
options?: { continueOnError?: boolean }
): Promise<void> {
for (const cmd of commands) {
try {
await this.exec(cmd);
} catch (err) {
if (!options?.continueOnError) {
throw err;
}
}
}
}
}