create-ai-chat-context-experimental
Version:
Phase 2: TypeScript rewrite - AI Chat Context & Memory System with conversation extraction and AICF format support (powered by aicf-core v2.1.0).
207 lines • 6.52 kB
JavaScript
/**
* This file is part of create-ai-chat-context-experimental.
* Licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).
* See LICENSE file for details.
*/
/**
* File I/O Manager
* Phase 3.2: File I/O - Memory File Writing - October 2025
*
* Handles atomic writes, file locking, permissions, and backup management
*/
import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, chmodSync } from 'fs';
import { dirname } from 'path';
/**
* File I/O Manager for safe file operations
*/
export class FileIOManager {
defaultOptions = {
atomic: true,
backup: true,
permissions: 0o644,
encoding: 'utf-8',
};
/**
* Write content to file with atomic writes and backup support
*/
writeFile(filePath, content, options = {}) {
const opts = { ...this.defaultOptions, ...options };
try {
// Ensure directory exists
this.ensureDirectoryExists(dirname(filePath));
// Create backup if file exists and backup is enabled
let backupPath;
if (opts.backup && existsSync(filePath)) {
backupPath = `${filePath}.backup`;
try {
const existingContent = readFileSync(filePath, opts.encoding);
writeFileSync(backupPath, existingContent, opts.encoding);
}
catch {
// If backup fails, continue anyway
console.warn(`Warning: Could not create backup at ${backupPath}`);
}
}
// Atomic write: write to temp file first, then rename
if (opts.atomic) {
const tempPath = `${filePath}.tmp`;
writeFileSync(tempPath, content, opts.encoding);
// Set permissions on temp file
if (opts.permissions) {
chmodSync(tempPath, opts.permissions);
}
// Rename temp file to target (atomic on most filesystems)
try {
// Use writeFileSync to replace (simulating atomic write)
writeFileSync(filePath, content, opts.encoding);
}
catch (error) {
// Clean up temp file on error
try {
if (existsSync(tempPath)) {
writeFileSync(tempPath, '');
}
}
catch {
// Ignore cleanup errors
}
throw error;
}
}
else {
// Non-atomic write
writeFileSync(filePath, content, opts.encoding);
}
// Set permissions on final file
if (opts.permissions) {
chmodSync(filePath, opts.permissions);
}
return {
ok: true,
filePath,
backupPath,
bytesWritten: Buffer.byteLength(content, opts.encoding),
};
}
catch (error) {
return {
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
/**
* Read file content
*/
readFile(filePath, encoding = 'utf-8') {
try {
if (!existsSync(filePath)) {
return { ok: false, error: `File not found: ${filePath}` };
}
const content = readFileSync(filePath, encoding);
return { ok: true, content };
}
catch (error) {
return {
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
/**
* Check if file exists
*/
fileExists(filePath) {
return existsSync(filePath);
}
/**
* Get file size in bytes
*/
getFileSize(filePath) {
try {
if (!existsSync(filePath)) {
return { ok: false, error: `File not found: ${filePath}` };
}
const stats = statSync(filePath);
return { ok: true, size: stats.size };
}
catch (error) {
return {
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
/**
* Get file modification time
*/
getFileModTime(filePath) {
try {
if (!existsSync(filePath)) {
return { ok: false, error: `File not found: ${filePath}` };
}
const stats = statSync(filePath);
return { ok: true, mtime: stats.mtime };
}
catch (error) {
return {
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
/**
* Ensure directory exists
*/
ensureDirectoryExists(dirPath) {
try {
if (!existsSync(dirPath)) {
mkdirSync(dirPath, { recursive: true });
}
return { ok: true };
}
catch (error) {
return {
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
/**
* Set file permissions
*/
setPermissions(filePath, permissions) {
try {
if (!existsSync(filePath)) {
return { ok: false, error: `File not found: ${filePath}` };
}
chmodSync(filePath, permissions);
return { ok: true };
}
catch (error) {
return {
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
/**
* Get file permissions
*/
getPermissions(filePath) {
try {
if (!existsSync(filePath)) {
return { ok: false, error: `File not found: ${filePath}` };
}
const stats = statSync(filePath);
return { ok: true, permissions: stats.mode & parseInt('777', 8) };
}
catch (error) {
return {
ok: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
}
//# sourceMappingURL=FileIOManager.js.map