codex-lens 0.1.13 → 0.1.14

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.
@@ -1,208 +0,0 @@
1
- #!/usr/bin/env node
2
- import { readFileSync, writeFileSync, statSync, readdirSync, mkdirSync, cpSync, rmSync, existsSync } from "fs";
3
- import { join, relative, extname } from "path";
4
- import { createLogger } from "./lib/logger.js";
5
- const logger = createLogger("SnapshotManager");
6
- const IGNORED_DIRS = [
7
- "node_modules",
8
- ".git",
9
- ".svn",
10
- ".hg",
11
- ".idea",
12
- ".vscode",
13
- "dist",
14
- "build",
15
- ".cache",
16
- "__pycache__",
17
- ".pytest_cache",
18
- ".next",
19
- ".nuxt",
20
- ".venv",
21
- ".env",
22
- ".DS_Store",
23
- ".codex-lens"
24
- ];
25
- const IGNORED_FILES = [
26
- ".DS_Store",
27
- "Thumbs.db",
28
- "desktop.ini"
29
- ];
30
- const IGNORED_EXTENSIONS = [
31
- ".log",
32
- ".lock"
33
- ];
34
- class SnapshotManager {
35
- constructor(snapshotsDir = ".codex-viewer/snapshots") {
36
- this.snapshotsDir = snapshotsDir;
37
- }
38
- async createSnapshot(projectRoot, taskId) {
39
- const snapshotPath = join(this.snapshotsDir, taskId);
40
- const metadataPath = join(snapshotPath, "snapshot.json");
41
- logger.info(`Creating snapshot: ${taskId}`);
42
- try {
43
- if (!existsSync(this.snapshotsDir)) {
44
- mkdirSync(this.snapshotsDir, { recursive: true });
45
- }
46
- if (existsSync(snapshotPath)) {
47
- rmSync(snapshotPath, { recursive: true, force: true });
48
- }
49
- mkdirSync(snapshotPath, { recursive: true });
50
- const files = this.scanProjectFiles(projectRoot);
51
- const metadata = {
52
- taskId,
53
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
54
- projectRoot,
55
- filesCount: files.length,
56
- files: []
57
- };
58
- for (const file of files) {
59
- const relativePath = relative(projectRoot, file);
60
- const destPath = join(snapshotPath, relativePath);
61
- const destDir = join(snapshotPath, relative(projectRoot, join(file, "..")));
62
- if (!existsSync(destDir)) {
63
- mkdirSync(destDir, { recursive: true });
64
- }
65
- try {
66
- cpSync(file, destPath, { force: true });
67
- const stats = statSync(file);
68
- metadata.files.push({
69
- path: relativePath,
70
- size: stats.size,
71
- mtime: stats.mtime.toISOString()
72
- });
73
- } catch (err) {
74
- logger.warn(`Failed to copy file ${file}: ${err.message}`);
75
- }
76
- }
77
- writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
78
- logger.info(`Snapshot created: ${taskId}, ${files.length} files`);
79
- return { success: true, snapshotPath, filesCount: files.length };
80
- } catch (error) {
81
- logger.error(`Failed to create snapshot: ${error.message}`);
82
- return { success: false, error: error.message };
83
- }
84
- }
85
- async restoreSnapshot(taskId) {
86
- const snapshotPath = join(this.snapshotsDir, taskId);
87
- const metadataPath = join(snapshotPath, "snapshot.json");
88
- logger.info(`Restoring snapshot: ${taskId}`);
89
- try {
90
- if (!existsSync(snapshotPath)) {
91
- return { success: false, error: "Snapshot not found" };
92
- }
93
- if (!existsSync(metadataPath)) {
94
- return { success: false, error: "Snapshot metadata not found" };
95
- }
96
- const metadata = JSON.parse(readFileSync(metadataPath, "utf-8"));
97
- const projectRoot = metadata.projectRoot;
98
- let restoredCount = 0;
99
- for (const fileInfo of metadata.files) {
100
- const sourcePath = join(snapshotPath, fileInfo.path);
101
- const destPath = join(projectRoot, fileInfo.path);
102
- if (!existsSync(sourcePath)) {
103
- continue;
104
- }
105
- const destDir = join(projectRoot, fileInfo.path.replace(/[^/\\]+$/, ""));
106
- if (!existsSync(destDir)) {
107
- mkdirSync(destDir, { recursive: true });
108
- }
109
- try {
110
- cpSync(sourcePath, destPath, { force: true });
111
- restoredCount++;
112
- } catch (err) {
113
- logger.warn(`Failed to restore file ${fileInfo.path}: ${err.message}`);
114
- }
115
- }
116
- logger.info(`Snapshot restored: ${taskId}, ${restoredCount} files`);
117
- return { success: true, restoredCount };
118
- } catch (error) {
119
- logger.error(`Failed to restore snapshot: ${error.message}`);
120
- return { success: false, error: error.message };
121
- }
122
- }
123
- async deleteSnapshot(taskId) {
124
- const snapshotPath = join(this.snapshotsDir, taskId);
125
- logger.info(`Deleting snapshot: ${taskId}`);
126
- try {
127
- if (existsSync(snapshotPath)) {
128
- rmSync(snapshotPath, { recursive: true, force: true });
129
- logger.info(`Snapshot deleted: ${taskId}`);
130
- return { success: true };
131
- }
132
- return { success: false, error: "Snapshot not found" };
133
- } catch (error) {
134
- logger.error(`Failed to delete snapshot: ${error.message}`);
135
- return { success: false, error: error.message };
136
- }
137
- }
138
- getSnapshot(taskId) {
139
- const snapshotPath = join(this.snapshotsDir, taskId);
140
- const metadataPath = join(snapshotPath, "snapshot.json");
141
- if (!existsSync(metadataPath)) {
142
- return null;
143
- }
144
- try {
145
- return JSON.parse(readFileSync(metadataPath, "utf-8"));
146
- } catch {
147
- return null;
148
- }
149
- }
150
- listSnapshots() {
151
- try {
152
- if (!existsSync(this.snapshotsDir)) {
153
- return [];
154
- }
155
- const entries = readdirSync(this.snapshotsDir, { withFileTypes: true });
156
- const snapshots = [];
157
- for (const entry of entries) {
158
- if (entry.isDirectory()) {
159
- const metadata = this.getSnapshot(entry.name);
160
- if (metadata) {
161
- snapshots.push(metadata);
162
- }
163
- }
164
- }
165
- return snapshots.sort(
166
- (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
167
- );
168
- } catch (error) {
169
- logger.error(`Failed to list snapshots: ${error.message}`);
170
- return [];
171
- }
172
- }
173
- scanProjectFiles(projectRoot) {
174
- const files = [];
175
- const scan = (dir) => {
176
- try {
177
- const entries = readdirSync(dir, { withFileTypes: true });
178
- for (const entry of entries) {
179
- const fullPath = join(dir, entry.name);
180
- if (entry.isDirectory()) {
181
- if (!IGNORED_DIRS.includes(entry.name) && !entry.name.startsWith(".")) {
182
- scan(fullPath);
183
- }
184
- } else if (entry.isFile()) {
185
- if (IGNORED_FILES.includes(entry.name)) {
186
- continue;
187
- }
188
- if (IGNORED_EXTENSIONS.some((ext) => entry.name.endsWith(ext))) {
189
- continue;
190
- }
191
- files.push(fullPath);
192
- }
193
- }
194
- } catch (err) {
195
- logger.warn(`Failed to scan directory ${dir}: ${err.message}`);
196
- }
197
- };
198
- scan(projectRoot);
199
- return files;
200
- }
201
- }
202
- function createSnapshotManager(snapshotsDir) {
203
- return new SnapshotManager(snapshotsDir);
204
- }
205
- export {
206
- SnapshotManager,
207
- createSnapshotManager
208
- };
@@ -1,230 +0,0 @@
1
- import { readFileSync, writeFileSync, statSync, readdirSync, mkdirSync, cpSync, rmSync, existsSync } from 'fs';
2
- import { join, relative, extname } from 'path';
3
- import { createLogger } from './lib/logger.js';
4
-
5
- const logger = createLogger('SnapshotManager');
6
-
7
- const IGNORED_DIRS = [
8
- 'node_modules', '.git', '.svn', '.hg',
9
- '.idea', '.vscode', 'dist', 'build', '.cache',
10
- '__pycache__', '.pytest_cache', '.next', '.nuxt',
11
- '.venv', '.env', '.DS_Store', '.codex-lens'
12
- ];
13
-
14
- const IGNORED_FILES = [
15
- '.DS_Store', 'Thumbs.db', 'desktop.ini'
16
- ];
17
-
18
- const IGNORED_EXTENSIONS = [
19
- '.log', '.lock'
20
- ];
21
-
22
- export class SnapshotManager {
23
- constructor(snapshotsDir = '.codex-viewer/snapshots') {
24
- this.snapshotsDir = snapshotsDir;
25
- }
26
-
27
- async createSnapshot(projectRoot, taskId) {
28
- const snapshotPath = join(this.snapshotsDir, taskId);
29
- const metadataPath = join(snapshotPath, 'snapshot.json');
30
-
31
- logger.info(`Creating snapshot: ${taskId}`);
32
-
33
- try {
34
- if (!existsSync(this.snapshotsDir)) {
35
- mkdirSync(this.snapshotsDir, { recursive: true });
36
- }
37
-
38
- if (existsSync(snapshotPath)) {
39
- rmSync(snapshotPath, { recursive: true, force: true });
40
- }
41
- mkdirSync(snapshotPath, { recursive: true });
42
-
43
- const files = this.scanProjectFiles(projectRoot);
44
- const metadata = {
45
- taskId,
46
- createdAt: new Date().toISOString(),
47
- projectRoot,
48
- filesCount: files.length,
49
- files: []
50
- };
51
-
52
- for (const file of files) {
53
- const relativePath = relative(projectRoot, file);
54
- const destPath = join(snapshotPath, relativePath);
55
- const destDir = join(snapshotPath, relative(projectRoot, join(file, '..')));
56
-
57
- if (!existsSync(destDir)) {
58
- mkdirSync(destDir, { recursive: true });
59
- }
60
-
61
- try {
62
- cpSync(file, destPath, { force: true });
63
- const stats = statSync(file);
64
- metadata.files.push({
65
- path: relativePath,
66
- size: stats.size,
67
- mtime: stats.mtime.toISOString()
68
- });
69
- } catch (err) {
70
- logger.warn(`Failed to copy file ${file}: ${err.message}`);
71
- }
72
- }
73
-
74
- writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
75
-
76
- logger.info(`Snapshot created: ${taskId}, ${files.length} files`);
77
- return { success: true, snapshotPath, filesCount: files.length };
78
-
79
- } catch (error) {
80
- logger.error(`Failed to create snapshot: ${error.message}`);
81
- return { success: false, error: error.message };
82
- }
83
- }
84
-
85
- async restoreSnapshot(taskId) {
86
- const snapshotPath = join(this.snapshotsDir, taskId);
87
- const metadataPath = join(snapshotPath, 'snapshot.json');
88
-
89
- logger.info(`Restoring snapshot: ${taskId}`);
90
-
91
- try {
92
- if (!existsSync(snapshotPath)) {
93
- return { success: false, error: 'Snapshot not found' };
94
- }
95
-
96
- if (!existsSync(metadataPath)) {
97
- return { success: false, error: 'Snapshot metadata not found' };
98
- }
99
-
100
- const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
101
- const projectRoot = metadata.projectRoot;
102
- let restoredCount = 0;
103
-
104
- for (const fileInfo of metadata.files) {
105
- const sourcePath = join(snapshotPath, fileInfo.path);
106
- const destPath = join(projectRoot, fileInfo.path);
107
-
108
- if (!existsSync(sourcePath)) {
109
- continue;
110
- }
111
-
112
- const destDir = join(projectRoot, fileInfo.path.replace(/[^/\\]+$/, ''));
113
- if (!existsSync(destDir)) {
114
- mkdirSync(destDir, { recursive: true });
115
- }
116
-
117
- try {
118
- cpSync(sourcePath, destPath, { force: true });
119
- restoredCount++;
120
- } catch (err) {
121
- logger.warn(`Failed to restore file ${fileInfo.path}: ${err.message}`);
122
- }
123
- }
124
-
125
- logger.info(`Snapshot restored: ${taskId}, ${restoredCount} files`);
126
- return { success: true, restoredCount };
127
-
128
- } catch (error) {
129
- logger.error(`Failed to restore snapshot: ${error.message}`);
130
- return { success: false, error: error.message };
131
- }
132
- }
133
-
134
- async deleteSnapshot(taskId) {
135
- const snapshotPath = join(this.snapshotsDir, taskId);
136
-
137
- logger.info(`Deleting snapshot: ${taskId}`);
138
-
139
- try {
140
- if (existsSync(snapshotPath)) {
141
- rmSync(snapshotPath, { recursive: true, force: true });
142
- logger.info(`Snapshot deleted: ${taskId}`);
143
- return { success: true };
144
- }
145
- return { success: false, error: 'Snapshot not found' };
146
- } catch (error) {
147
- logger.error(`Failed to delete snapshot: ${error.message}`);
148
- return { success: false, error: error.message };
149
- }
150
- }
151
-
152
- getSnapshot(taskId) {
153
- const snapshotPath = join(this.snapshotsDir, taskId);
154
- const metadataPath = join(snapshotPath, 'snapshot.json');
155
-
156
- if (!existsSync(metadataPath)) {
157
- return null;
158
- }
159
-
160
- try {
161
- return JSON.parse(readFileSync(metadataPath, 'utf-8'));
162
- } catch {
163
- return null;
164
- }
165
- }
166
-
167
- listSnapshots() {
168
- try {
169
- if (!existsSync(this.snapshotsDir)) {
170
- return [];
171
- }
172
-
173
- const entries = readdirSync(this.snapshotsDir, { withFileTypes: true });
174
- const snapshots = [];
175
-
176
- for (const entry of entries) {
177
- if (entry.isDirectory()) {
178
- const metadata = this.getSnapshot(entry.name);
179
- if (metadata) {
180
- snapshots.push(metadata);
181
- }
182
- }
183
- }
184
-
185
- return snapshots.sort((a, b) =>
186
- new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
187
- );
188
- } catch (error) {
189
- logger.error(`Failed to list snapshots: ${error.message}`);
190
- return [];
191
- }
192
- }
193
-
194
- scanProjectFiles(projectRoot) {
195
- const files = [];
196
-
197
- const scan = (dir) => {
198
- try {
199
- const entries = readdirSync(dir, { withFileTypes: true });
200
-
201
- for (const entry of entries) {
202
- const fullPath = join(dir, entry.name);
203
-
204
- if (entry.isDirectory()) {
205
- if (!IGNORED_DIRS.includes(entry.name) && !entry.name.startsWith('.')) {
206
- scan(fullPath);
207
- }
208
- } else if (entry.isFile()) {
209
- if (IGNORED_FILES.includes(entry.name)) {
210
- continue;
211
- }
212
- if (IGNORED_EXTENSIONS.some(ext => entry.name.endsWith(ext))) {
213
- continue;
214
- }
215
- files.push(fullPath);
216
- }
217
- }
218
- } catch (err) {
219
- logger.warn(`Failed to scan directory ${dir}: ${err.message}`);
220
- }
221
- };
222
-
223
- scan(projectRoot);
224
- return files;
225
- }
226
- }
227
-
228
- export function createSnapshotManager(snapshotsDir) {
229
- return new SnapshotManager(snapshotsDir);
230
- }