octie-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +523 -0
- package/dist/cli/commands/approve.d.ts +27 -0
- package/dist/cli/commands/approve.d.ts.map +1 -0
- package/dist/cli/commands/approve.js +119 -0
- package/dist/cli/commands/approve.js.map +1 -0
- package/dist/cli/commands/batch.d.ts +15 -0
- package/dist/cli/commands/batch.d.ts.map +1 -0
- package/dist/cli/commands/batch.js +521 -0
- package/dist/cli/commands/batch.js.map +1 -0
- package/dist/cli/commands/create.d.ts +9 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +321 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +9 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +143 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/export.d.ts +9 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +66 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/find.d.ts +16 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +252 -0
- package/dist/cli/commands/find.js.map +1 -0
- package/dist/cli/commands/get.d.ts +9 -0
- package/dist/cli/commands/get.d.ts.map +1 -0
- package/dist/cli/commands/get.js +74 -0
- package/dist/cli/commands/get.js.map +1 -0
- package/dist/cli/commands/graph.d.ts +9 -0
- package/dist/cli/commands/graph.d.ts.map +1 -0
- package/dist/cli/commands/graph.js +200 -0
- package/dist/cli/commands/graph.js.map +1 -0
- package/dist/cli/commands/import.d.ts +9 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +807 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +57 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +9 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +175 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/merge.d.ts +9 -0
- package/dist/cli/commands/merge.d.ts.map +1 -0
- package/dist/cli/commands/merge.js +113 -0
- package/dist/cli/commands/merge.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +9 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +94 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/update.d.ts +9 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +423 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/wire.d.ts +15 -0
- package/dist/cli/commands/wire.d.ts.map +1 -0
- package/dist/cli/commands/wire.js +164 -0
- package/dist/cli/commands/wire.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +100 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output/json.d.ts +16 -0
- package/dist/cli/output/json.d.ts.map +1 -0
- package/dist/cli/output/json.js +29 -0
- package/dist/cli/output/json.js.map +1 -0
- package/dist/cli/output/markdown.d.ts +15 -0
- package/dist/cli/output/markdown.d.ts.map +1 -0
- package/dist/cli/output/markdown.js +206 -0
- package/dist/cli/output/markdown.js.map +1 -0
- package/dist/cli/output/table.d.ts +23 -0
- package/dist/cli/output/table.d.ts.map +1 -0
- package/dist/cli/output/table.js +150 -0
- package/dist/cli/output/table.js.map +1 -0
- package/dist/cli/utils/helpers.d.ts +126 -0
- package/dist/cli/utils/helpers.d.ts.map +1 -0
- package/dist/cli/utils/helpers.js +325 -0
- package/dist/cli/utils/helpers.js.map +1 -0
- package/dist/core/graph/algorithms.d.ts +11 -0
- package/dist/core/graph/algorithms.d.ts.map +1 -0
- package/dist/core/graph/algorithms.js +14 -0
- package/dist/core/graph/algorithms.js.map +1 -0
- package/dist/core/graph/cycle.d.ts +155 -0
- package/dist/core/graph/cycle.d.ts.map +1 -0
- package/dist/core/graph/cycle.js +297 -0
- package/dist/core/graph/cycle.js.map +1 -0
- package/dist/core/graph/index.d.ts +223 -0
- package/dist/core/graph/index.d.ts.map +1 -0
- package/dist/core/graph/index.js +475 -0
- package/dist/core/graph/index.js.map +1 -0
- package/dist/core/graph/operations.d.ts +240 -0
- package/dist/core/graph/operations.d.ts.map +1 -0
- package/dist/core/graph/operations.js +503 -0
- package/dist/core/graph/operations.js.map +1 -0
- package/dist/core/graph/sort.d.ts +76 -0
- package/dist/core/graph/sort.d.ts.map +1 -0
- package/dist/core/graph/sort.js +254 -0
- package/dist/core/graph/sort.js.map +1 -0
- package/dist/core/graph/traversal.d.ts +122 -0
- package/dist/core/graph/traversal.d.ts.map +1 -0
- package/dist/core/graph/traversal.js +336 -0
- package/dist/core/graph/traversal.js.map +1 -0
- package/dist/core/models/task-node.d.ts +328 -0
- package/dist/core/models/task-node.d.ts.map +1 -0
- package/dist/core/models/task-node.js +1090 -0
- package/dist/core/models/task-node.js.map +1 -0
- package/dist/core/registry/index.d.ts +102 -0
- package/dist/core/registry/index.d.ts.map +1 -0
- package/dist/core/registry/index.js +249 -0
- package/dist/core/registry/index.js.map +1 -0
- package/dist/core/registry/root-guard.d.ts +19 -0
- package/dist/core/registry/root-guard.d.ts.map +1 -0
- package/dist/core/registry/root-guard.js +28 -0
- package/dist/core/registry/root-guard.js.map +1 -0
- package/dist/core/storage/atomic-write.d.ts +181 -0
- package/dist/core/storage/atomic-write.d.ts.map +1 -0
- package/dist/core/storage/atomic-write.js +379 -0
- package/dist/core/storage/atomic-write.js.map +1 -0
- package/dist/core/storage/file-store.d.ts +148 -0
- package/dist/core/storage/file-store.d.ts.map +1 -0
- package/dist/core/storage/file-store.js +423 -0
- package/dist/core/storage/file-store.js.map +1 -0
- package/dist/core/storage/indexer.d.ts +138 -0
- package/dist/core/storage/indexer.d.ts.map +1 -0
- package/dist/core/storage/indexer.js +350 -0
- package/dist/core/storage/indexer.js.map +1 -0
- package/dist/core/utils/status-helpers.d.ts +59 -0
- package/dist/core/utils/status-helpers.d.ts.map +1 -0
- package/dist/core/utils/status-helpers.js +149 -0
- package/dist/core/utils/status-helpers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +504 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +182 -0
- package/dist/types/index.js.map +1 -0
- package/dist/web/routes/graph.d.ts +17 -0
- package/dist/web/routes/graph.d.ts.map +1 -0
- package/dist/web/routes/graph.js +277 -0
- package/dist/web/routes/graph.js.map +1 -0
- package/dist/web/routes/projects.d.ts +14 -0
- package/dist/web/routes/projects.d.ts.map +1 -0
- package/dist/web/routes/projects.js +102 -0
- package/dist/web/routes/projects.js.map +1 -0
- package/dist/web/routes/tasks.d.ts +17 -0
- package/dist/web/routes/tasks.d.ts.map +1 -0
- package/dist/web/routes/tasks.js +538 -0
- package/dist/web/routes/tasks.js.map +1 -0
- package/dist/web/server.d.ts +121 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +389 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web-ui/assets/index-BB0qvF1y.css +1 -0
- package/dist/web-ui/assets/index-Vmm72oKY.js +34 -0
- package/dist/web-ui/index.html +14 -0
- package/dist/web-ui/vite.svg +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic file write operations
|
|
3
|
+
*
|
|
4
|
+
* Implements safe file writes using temp file + rename strategy.
|
|
5
|
+
* Ensures data integrity by:
|
|
6
|
+
* 1. Writing to temporary file first
|
|
7
|
+
* 2. Verifying write success
|
|
8
|
+
* 3. Creating backup of existing file
|
|
9
|
+
* 4. Atomic rename to final location
|
|
10
|
+
*
|
|
11
|
+
* @module core/storage/atomic-write
|
|
12
|
+
*/
|
|
13
|
+
import { promises as fs } from 'node:fs';
|
|
14
|
+
import { join, sep, normalize, isAbsolute } from 'node:path';
|
|
15
|
+
import { tmpdir } from 'node:os';
|
|
16
|
+
import { FileOperationError } from '../../types/index.js';
|
|
17
|
+
/**
|
|
18
|
+
* Default configuration for atomic writes
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_CONFIG = {
|
|
21
|
+
backupCount: 5,
|
|
22
|
+
tempDir: tmpdir(),
|
|
23
|
+
tempPrefix: '.octie-tmp-',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Atomic File Writer class
|
|
27
|
+
*
|
|
28
|
+
* Provides safe file write operations using atomic rename strategy.
|
|
29
|
+
* Prevents data corruption by writing to temp file first, then renaming.
|
|
30
|
+
*/
|
|
31
|
+
export class AtomicFileWriter {
|
|
32
|
+
_config;
|
|
33
|
+
/**
|
|
34
|
+
* Create a new AtomicFileWriter
|
|
35
|
+
* @param config - Optional configuration
|
|
36
|
+
*/
|
|
37
|
+
constructor(config = {}) {
|
|
38
|
+
this._config = {
|
|
39
|
+
backupCount: config.backupCount ?? DEFAULT_CONFIG.backupCount,
|
|
40
|
+
tempDir: config.tempDir ?? DEFAULT_CONFIG.tempDir,
|
|
41
|
+
tempPrefix: config.tempPrefix ?? DEFAULT_CONFIG.tempPrefix,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Write data to file atomically
|
|
46
|
+
*
|
|
47
|
+
* Process:
|
|
48
|
+
* 1. Write to temporary file
|
|
49
|
+
* 2. Verify write success (check file size)
|
|
50
|
+
* 3. Create backup of existing file (if exists)
|
|
51
|
+
* 4. Atomic rename to final location
|
|
52
|
+
*
|
|
53
|
+
* @param filePath - Target file path
|
|
54
|
+
* @param data - Data to write (will be JSON stringified if object)
|
|
55
|
+
* @param options - Write options
|
|
56
|
+
* @throws {FileOperationError} If write operation fails
|
|
57
|
+
*/
|
|
58
|
+
async write(filePath, data, options = {}) {
|
|
59
|
+
const { createBackup = true, indent = 2 } = options;
|
|
60
|
+
// Prepare content
|
|
61
|
+
let content;
|
|
62
|
+
if (typeof data === 'string') {
|
|
63
|
+
content = data;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
content = JSON.stringify(data, null, indent);
|
|
67
|
+
}
|
|
68
|
+
// Validate content is not empty
|
|
69
|
+
if (content.length === 0) {
|
|
70
|
+
throw new FileOperationError('Cannot write empty content', filePath);
|
|
71
|
+
}
|
|
72
|
+
// Generate temp file path
|
|
73
|
+
const tempPath = this._getTempPath(filePath);
|
|
74
|
+
try {
|
|
75
|
+
// Step 1: Write to temporary file
|
|
76
|
+
await fs.writeFile(tempPath, content, 'utf8');
|
|
77
|
+
// Step 2: Verify write succeeded
|
|
78
|
+
const stats = await fs.stat(tempPath);
|
|
79
|
+
if (stats.size === 0) {
|
|
80
|
+
throw new FileOperationError('Write produced empty file', filePath);
|
|
81
|
+
}
|
|
82
|
+
// Use Buffer.byteLength for proper Unicode handling
|
|
83
|
+
const expectedBytes = Buffer.byteLength(content, 'utf8');
|
|
84
|
+
if (stats.size !== expectedBytes) {
|
|
85
|
+
throw new FileOperationError(`Write size mismatch: expected ${expectedBytes} bytes, got ${stats.size} bytes`, filePath);
|
|
86
|
+
}
|
|
87
|
+
// Step 3: Create backup if file exists and backup requested
|
|
88
|
+
if (createBackup) {
|
|
89
|
+
await this._createBackup(filePath);
|
|
90
|
+
}
|
|
91
|
+
// Step 4: Atomic rename to final location
|
|
92
|
+
await fs.rename(tempPath, filePath);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// Cleanup temp file on failure
|
|
96
|
+
try {
|
|
97
|
+
await fs.unlink(tempPath);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Ignore cleanup errors
|
|
101
|
+
}
|
|
102
|
+
if (error instanceof FileOperationError) {
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
throw new FileOperationError(`Atomic write failed: ${error instanceof Error ? error.message : String(error)}`, filePath);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Read file contents
|
|
110
|
+
* @param filePath - File path to read
|
|
111
|
+
* @returns File contents as string
|
|
112
|
+
* @throws {FileOperationError} If read fails
|
|
113
|
+
*/
|
|
114
|
+
async read(filePath) {
|
|
115
|
+
try {
|
|
116
|
+
return await fs.readFile(filePath, 'utf8');
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
throw new FileOperationError(`Read failed: ${error instanceof Error ? error.message : String(error)}`, filePath);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Read and parse JSON file
|
|
124
|
+
* @param filePath - File path to read
|
|
125
|
+
* @returns Parsed JSON object
|
|
126
|
+
* @throws {FileOperationError} If read or parse fails
|
|
127
|
+
*/
|
|
128
|
+
async readJSON(filePath) {
|
|
129
|
+
try {
|
|
130
|
+
const content = await this.read(filePath);
|
|
131
|
+
return JSON.parse(content);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (error instanceof FileOperationError) {
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
throw new FileOperationError(`JSON parse failed: ${error instanceof Error ? error.message : String(error)}`, filePath);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Create backup of existing file
|
|
142
|
+
* @param filePath - File to backup
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
async _createBackup(filePath) {
|
|
146
|
+
try {
|
|
147
|
+
// Check if file exists
|
|
148
|
+
await fs.access(filePath);
|
|
149
|
+
// Create backup path
|
|
150
|
+
const backupPath = this._getBackupPath(filePath);
|
|
151
|
+
// Copy to backup
|
|
152
|
+
await fs.copyFile(filePath, backupPath);
|
|
153
|
+
// Rotate old backups
|
|
154
|
+
await this._rotateBackups(filePath);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
// If file doesn't exist, that's ok - no backup needed
|
|
158
|
+
if (error.code === 'ENOENT') {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Log but don't fail on backup errors
|
|
162
|
+
console.warn(`Backup creation failed for ${filePath}:`, error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Rotate backup files, keeping only the configured number
|
|
167
|
+
* @param filePath - Original file path
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
async _rotateBackups(filePath) {
|
|
171
|
+
const dir = this._getDirPath(filePath);
|
|
172
|
+
const baseName = this._getBaseName(filePath);
|
|
173
|
+
try {
|
|
174
|
+
// List existing backup files
|
|
175
|
+
const files = await fs.readdir(dir);
|
|
176
|
+
const backupFiles = files
|
|
177
|
+
.filter(f => f.startsWith(`${baseName}.bak`) || f.startsWith(`${baseName}.bak.`))
|
|
178
|
+
.sort()
|
|
179
|
+
.reverse(); // Newest first
|
|
180
|
+
// Remove excess backups
|
|
181
|
+
const backupsToDelete = backupFiles.slice(this._config.backupCount);
|
|
182
|
+
for (const file of backupsToDelete) {
|
|
183
|
+
await fs.unlink(join(dir, file));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
// Log but don't fail on rotation errors
|
|
188
|
+
console.warn(`Backup rotation failed for ${filePath}:`, error);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get backup file path
|
|
193
|
+
* @param filePath - Original file path
|
|
194
|
+
* @returns Backup file path
|
|
195
|
+
* @private
|
|
196
|
+
*/
|
|
197
|
+
_getBackupPath(filePath) {
|
|
198
|
+
const dir = this._getDirPath(filePath);
|
|
199
|
+
const baseName = this._getBaseName(filePath);
|
|
200
|
+
const timestamp = Date.now();
|
|
201
|
+
return join(dir, `${baseName}.bak.${timestamp}`);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get temporary file path
|
|
205
|
+
* @param filePath - Target file path
|
|
206
|
+
* @returns Temporary file path
|
|
207
|
+
* @private
|
|
208
|
+
*/
|
|
209
|
+
_getTempPath(filePath) {
|
|
210
|
+
const dir = this._getDirPath(filePath);
|
|
211
|
+
const baseName = this._getBaseName(filePath);
|
|
212
|
+
const timestamp = Date.now();
|
|
213
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
214
|
+
// Use same directory as target file for cross-device compatibility (Windows EXDEV fix)
|
|
215
|
+
return join(dir, `${this._config.tempPrefix}${baseName}-${timestamp}-${random}.tmp`);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Get directory path from file path
|
|
219
|
+
* @param filePath - File path
|
|
220
|
+
* @returns Directory path
|
|
221
|
+
* @private
|
|
222
|
+
*/
|
|
223
|
+
_getDirPath(filePath) {
|
|
224
|
+
const parts = filePath.split(sep);
|
|
225
|
+
parts.pop(); // Remove file name
|
|
226
|
+
return parts.join(sep) || '.';
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get base name from file path (without extension)
|
|
230
|
+
* @param filePath - File path
|
|
231
|
+
* @returns Base name
|
|
232
|
+
* @private
|
|
233
|
+
*/
|
|
234
|
+
_getBaseName(filePath) {
|
|
235
|
+
const parts = filePath.split(sep);
|
|
236
|
+
const fileName = parts[parts.length - 1] || '';
|
|
237
|
+
// Remove extension
|
|
238
|
+
const lastDot = fileName.lastIndexOf('.');
|
|
239
|
+
return lastDot > 0 ? fileName.substring(0, lastDot) : fileName;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Check if file exists
|
|
243
|
+
* @param filePath - File path to check
|
|
244
|
+
* @returns True if file exists
|
|
245
|
+
*/
|
|
246
|
+
async exists(filePath) {
|
|
247
|
+
try {
|
|
248
|
+
await fs.access(filePath);
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Delete file
|
|
257
|
+
* @param filePath - File path to delete
|
|
258
|
+
* @throws {FileOperationError} If delete fails
|
|
259
|
+
*/
|
|
260
|
+
async delete(filePath) {
|
|
261
|
+
try {
|
|
262
|
+
await fs.unlink(filePath);
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
if (error.code === 'ENOENT') {
|
|
266
|
+
return; // Already deleted
|
|
267
|
+
}
|
|
268
|
+
throw new FileOperationError(`Delete failed: ${error instanceof Error ? error.message : String(error)}`, filePath);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Ensure directory exists, create if missing
|
|
273
|
+
* @param dirPath - Directory path
|
|
274
|
+
* @throws {FileOperationError} If directory creation fails
|
|
275
|
+
*/
|
|
276
|
+
async ensureDir(dirPath) {
|
|
277
|
+
try {
|
|
278
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
throw new FileOperationError(`Directory creation failed: ${error instanceof Error ? error.message : String(error)}`, dirPath);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Cross-platform path utilities
|
|
287
|
+
*/
|
|
288
|
+
export class PathUtils {
|
|
289
|
+
/**
|
|
290
|
+
* Normalize path for consistent storage
|
|
291
|
+
* Converts backslashes to forward slashes, removes redundant separators
|
|
292
|
+
* @param path - Path to normalize
|
|
293
|
+
* @returns Normalized path
|
|
294
|
+
*/
|
|
295
|
+
static normalizePath(path) {
|
|
296
|
+
return normalize(path).split(sep).join('/');
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Join path segments
|
|
300
|
+
* @param segments - Path segments to join
|
|
301
|
+
* @returns Joined path
|
|
302
|
+
*/
|
|
303
|
+
static join(...segments) {
|
|
304
|
+
return join(...segments);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Check if path is absolute
|
|
308
|
+
* @param path - Path to check
|
|
309
|
+
* @returns True if path is absolute
|
|
310
|
+
*/
|
|
311
|
+
static isAbsolute(path) {
|
|
312
|
+
return isAbsolute(path);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Make path relative to another path
|
|
316
|
+
* @param from - Base path
|
|
317
|
+
* @param to - Target path
|
|
318
|
+
* @returns Relative path
|
|
319
|
+
*/
|
|
320
|
+
static relative(from, to) {
|
|
321
|
+
// Use relative from path module
|
|
322
|
+
const { relative } = require('node:path');
|
|
323
|
+
return relative(from, to);
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Get project configuration path
|
|
327
|
+
* Platform-aware configuration directory
|
|
328
|
+
* @param projectName - Project name
|
|
329
|
+
* @returns Configuration path
|
|
330
|
+
*/
|
|
331
|
+
static getConfigPath(projectName) {
|
|
332
|
+
const platform = process.platform;
|
|
333
|
+
const homedir = require('node:os').homedir();
|
|
334
|
+
switch (platform) {
|
|
335
|
+
case 'win32':
|
|
336
|
+
return join(process.env.APPDATA || homedir, projectName);
|
|
337
|
+
case 'darwin':
|
|
338
|
+
return join(homedir, 'Library', 'Application Support', projectName);
|
|
339
|
+
default: // linux and others
|
|
340
|
+
return join(homedir, '.config', projectName);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get project data path
|
|
345
|
+
* Platform-aware data directory
|
|
346
|
+
* @param projectName - Project name
|
|
347
|
+
* @returns Data path
|
|
348
|
+
*/
|
|
349
|
+
static getDataPath(projectName) {
|
|
350
|
+
const platform = process.platform;
|
|
351
|
+
const homedir = require('node:os').homedir();
|
|
352
|
+
switch (platform) {
|
|
353
|
+
case 'win32':
|
|
354
|
+
return join(process.env.LOCALAPPDATA || join(homedir, 'AppData', 'Local'), projectName);
|
|
355
|
+
case 'darwin':
|
|
356
|
+
return join(homedir, 'Library', 'Application Support', projectName);
|
|
357
|
+
default: // linux and others
|
|
358
|
+
return join(homedir, '.local', 'share', projectName);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Sanitize file path to prevent directory traversal
|
|
363
|
+
* @param filePath - File path to sanitize
|
|
364
|
+
* @param basePath - Base path to resolve against
|
|
365
|
+
* @returns Sanitized, absolute path
|
|
366
|
+
* @throws {FileOperationError} If path tries to escape base directory
|
|
367
|
+
*/
|
|
368
|
+
static sanitizePath(filePath, basePath = process.cwd()) {
|
|
369
|
+
const normalized = normalize(filePath);
|
|
370
|
+
const resolved = join(basePath, normalized);
|
|
371
|
+
// Check if resolved path is within base path
|
|
372
|
+
const relativePath = this.relative(basePath, resolved);
|
|
373
|
+
if (relativePath.startsWith('..')) {
|
|
374
|
+
throw new FileOperationError('Path traversal detected: file path cannot escape base directory', filePath);
|
|
375
|
+
}
|
|
376
|
+
return resolved;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=atomic-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../../../src/core/storage/atomic-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Storage for file operations
|
|
3
|
+
*
|
|
4
|
+
* Manages persistent storage of task graphs using atomic file operations.
|
|
5
|
+
* Handles project.json, backups, and .octie directory structure.
|
|
6
|
+
*
|
|
7
|
+
* Directory Structure:
|
|
8
|
+
* .octie/
|
|
9
|
+
* ├── project.json # Main task storage
|
|
10
|
+
* ├── project.json.bak # Latest backup
|
|
11
|
+
* ├── project.json.bak.{ts} # Rotated backups
|
|
12
|
+
* ├── indexes/ # Pre-computed indexes
|
|
13
|
+
* ├── cache/ # Serialized graph cache
|
|
14
|
+
* └── config.json # Project configuration
|
|
15
|
+
*
|
|
16
|
+
* @module core/storage
|
|
17
|
+
*/
|
|
18
|
+
import type { ProjectMetadata } from '../../types/index.js';
|
|
19
|
+
import { TaskGraphStore } from '../graph/index.js';
|
|
20
|
+
/**
|
|
21
|
+
* Task Storage configuration
|
|
22
|
+
*/
|
|
23
|
+
export interface TaskStorageConfig {
|
|
24
|
+
/** Project directory path */
|
|
25
|
+
projectDir?: string;
|
|
26
|
+
/** Octie directory name (default: '.octie') */
|
|
27
|
+
octieDirName?: string;
|
|
28
|
+
/** Project file name (default: 'project.json') */
|
|
29
|
+
projectFileName?: string;
|
|
30
|
+
/** Auto-backup enabled (default: true) */
|
|
31
|
+
autoBackup?: boolean;
|
|
32
|
+
/** Number of backups to keep (default: 5) */
|
|
33
|
+
backupCount?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Task Storage class
|
|
37
|
+
*
|
|
38
|
+
* Manages persistent storage of task graphs with atomic operations.
|
|
39
|
+
*/
|
|
40
|
+
export declare class TaskStorage {
|
|
41
|
+
private _projectDir;
|
|
42
|
+
private _octieDirName;
|
|
43
|
+
private _projectFileName;
|
|
44
|
+
private _autoBackup;
|
|
45
|
+
private _backupCount;
|
|
46
|
+
private _writer;
|
|
47
|
+
/**
|
|
48
|
+
* Create a new TaskStorage instance
|
|
49
|
+
* @param config - Storage configuration
|
|
50
|
+
*/
|
|
51
|
+
constructor(config?: TaskStorageConfig);
|
|
52
|
+
/**
|
|
53
|
+
* Get the Octie directory path
|
|
54
|
+
*/
|
|
55
|
+
get octieDirPath(): string;
|
|
56
|
+
/**
|
|
57
|
+
* Get the project file path
|
|
58
|
+
*/
|
|
59
|
+
get projectFilePath(): string;
|
|
60
|
+
/**
|
|
61
|
+
* Get the backup file path
|
|
62
|
+
*/
|
|
63
|
+
get backupFilePath(): string;
|
|
64
|
+
/**
|
|
65
|
+
* Get the indexes directory path
|
|
66
|
+
*/
|
|
67
|
+
get indexesDirPath(): string;
|
|
68
|
+
/**
|
|
69
|
+
* Get the cache directory path
|
|
70
|
+
*/
|
|
71
|
+
get cacheDirPath(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Get the config file path
|
|
74
|
+
*/
|
|
75
|
+
get configFilePath(): string;
|
|
76
|
+
/**
|
|
77
|
+
* Initialize the Octie directory structure
|
|
78
|
+
* Creates .octie directory with subdirectories if they don't exist
|
|
79
|
+
*/
|
|
80
|
+
init(): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Check if Octie directory exists
|
|
83
|
+
* @returns True if .octie directory exists
|
|
84
|
+
*/
|
|
85
|
+
exists(): Promise<boolean>;
|
|
86
|
+
/**
|
|
87
|
+
* Load project from file
|
|
88
|
+
* @returns TaskGraphStore instance
|
|
89
|
+
* @throws {FileOperationError} If file doesn't exist or is invalid
|
|
90
|
+
*/
|
|
91
|
+
load(): Promise<TaskGraphStore>;
|
|
92
|
+
/**
|
|
93
|
+
* Save project to file
|
|
94
|
+
* @param graph - TaskGraphStore to save
|
|
95
|
+
* @param options - Save options
|
|
96
|
+
*/
|
|
97
|
+
save(graph: TaskGraphStore, options?: {
|
|
98
|
+
createBackup?: boolean;
|
|
99
|
+
}): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Build indexes for fast lookups
|
|
102
|
+
* @param graph - TaskGraphStore to index
|
|
103
|
+
* @returns ProjectIndexes
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
private _buildIndexes;
|
|
107
|
+
/**
|
|
108
|
+
* Validate project file structure
|
|
109
|
+
* @param projectFile - Project file to validate
|
|
110
|
+
* @throws {ValidationError} If structure is invalid
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
private _validateProjectFile;
|
|
114
|
+
/**
|
|
115
|
+
* Get project metadata only (faster than full load)
|
|
116
|
+
* @returns Project metadata
|
|
117
|
+
* @throws {FileOperationError} If file doesn't exist
|
|
118
|
+
*/
|
|
119
|
+
getMetadata(): Promise<ProjectMetadata>;
|
|
120
|
+
/**
|
|
121
|
+
* Delete project file and backups
|
|
122
|
+
* Use with caution - this is destructive
|
|
123
|
+
*/
|
|
124
|
+
delete(): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Create a new project with default metadata
|
|
127
|
+
* @param projectName - Project name
|
|
128
|
+
* @param description - Optional project description
|
|
129
|
+
*/
|
|
130
|
+
createProject(projectName: string, description?: string): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* List backup files
|
|
133
|
+
* @returns Array of backup file paths
|
|
134
|
+
*/
|
|
135
|
+
listBackups(): Promise<string[]>;
|
|
136
|
+
/**
|
|
137
|
+
* Restore from latest backup
|
|
138
|
+
* @throws {FileOperationError} If no backup exists
|
|
139
|
+
*/
|
|
140
|
+
restoreFromBackup(): Promise<void>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get project path for current directory
|
|
144
|
+
* Searches upward from current directory for .octie folder
|
|
145
|
+
* @returns Project directory path or undefined if not found
|
|
146
|
+
*/
|
|
147
|
+
export declare function findProjectPath(startDir?: string): Promise<string | undefined>;
|
|
148
|
+
//# sourceMappingURL=file-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../src/core/storage/file-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAA+B,eAAe,EAAa,MAAM,sBAAsB,CAAC;AAGpG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAanD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAmB;IAElC;;;OAGG;gBACS,MAAM,GAAE,iBAAsB;IAY1C;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC;IAwCrC;;;;OAIG;IACG,IAAI,CACR,KAAK,EAAE,cAAc,EACrB,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAO,GACvC,OAAO,CAAC,IAAI,CAAC;IA8ChB;;;;;OAKG;YACW,aAAa;IAiE3B;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAwB5B;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAmB7C;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB7B;;;;OAIG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2C7E;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAkBtC;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAwBzC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4BnG"}
|