cwresdev 0.2.1 → 0.2.3

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/bin/cwgit.js CHANGED
@@ -49,10 +49,8 @@ async function main() {
49
49
  const docRoot = resolveDocRoot(workspaceRoot);
50
50
 
51
51
  if (command === "init") {
52
- const { fileCount, basePath } = await initBase(targetPath, docRoot);
53
- process.stdout.write(`[cwgit] Base snapshot created: ${fileCount} files tracked.\n`);
54
- process.stdout.write(`[cwgit] Stored at: ${basePath}\n`);
55
- process.stdout.write(`[cwgit] Tip: add .cwgit/ to .gitignore if using Git.\n`);
52
+ await initBase(targetPath, docRoot);
53
+ process.stdout.write("[cwgit] Successfully initiated.\n");
56
54
  return;
57
55
  }
58
56
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cwresdev",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "private": false,
package/src/cwgit.js CHANGED
@@ -195,10 +195,9 @@ async function initBase(projectDir, docRoot) {
195
195
  const filePaths = await collectFiles(resolvedProject, resolvedProject);
196
196
  const fileCount = filePaths.length;
197
197
 
198
- process.stderr.write(`[cwgit] Hashing ${fileCount} files...\n`);
199
-
200
198
  const files = {};
201
199
  let processed = 0;
200
+ let lastPercent = -1;
202
201
 
203
202
  for (const filePath of filePaths) {
204
203
  const relFilePath = path.relative(resolvedProject, filePath).replace(/\\/g, "/");
@@ -207,7 +206,6 @@ async function initBase(projectDir, docRoot) {
207
206
  files[relFilePath] = await hashFile(filePath);
208
207
  } catch (err) {
209
208
  if (err.code === "EBUSY" || err.code === "EPERM" || err.code === "ENOENT") {
210
- process.stderr.write(`[cwgit] Warning: skipped inaccessible file: ${relFilePath}\n`);
211
209
  continue;
212
210
  }
213
211
 
@@ -215,12 +213,16 @@ async function initBase(projectDir, docRoot) {
215
213
  }
216
214
 
217
215
  processed += 1;
216
+ const percent = Math.floor((processed / fileCount) * 100);
218
217
 
219
- if (processed % 100 === 0) {
220
- process.stderr.write(`[cwgit] ${processed}/${fileCount} files hashed\n`);
218
+ if (percent !== lastPercent) {
219
+ lastPercent = percent;
220
+ process.stderr.write(`\r[cwgit] ${percent}%`);
221
221
  }
222
222
  }
223
223
 
224
+ process.stderr.write("\n");
225
+
224
226
  const baseData = {
225
227
  version: 1,
226
228
  createdAt: new Date().toISOString(),
@@ -265,7 +267,10 @@ async function detectChanges(projectDir, docRoot) {
265
267
  const currentPaths = await collectFiles(resolvedProject, resolvedProject);
266
268
  const currentFiles = {};
267
269
 
268
- process.stderr.write(`[cwgit] Scanning ${currentPaths.length} files...\n`);
270
+ process.stderr.write(`\r[cwgit] 0%`);
271
+
272
+ let scanned = 0;
273
+ let lastScanPercent = -1;
269
274
 
270
275
  for (const filePath of currentPaths) {
271
276
  const relFilePath = path.relative(resolvedProject, filePath).replace(/\\/g, "/");
@@ -274,29 +279,54 @@ async function detectChanges(projectDir, docRoot) {
274
279
  currentFiles[relFilePath] = await hashFile(filePath);
275
280
  } catch (err) {
276
281
  if (err.code === "EBUSY" || err.code === "EPERM" || err.code === "ENOENT") {
277
- process.stderr.write(`[cwgit] Warning: skipped inaccessible file: ${relFilePath}\n`);
278
282
  continue;
279
283
  }
280
284
 
281
285
  throw err;
282
286
  }
287
+
288
+ scanned += 1;
289
+ const pct = Math.floor((scanned / currentPaths.length) * 100);
290
+
291
+ if (pct !== lastScanPercent) {
292
+ lastScanPercent = pct;
293
+ process.stderr.write(`\r[cwgit] ${pct}%`);
294
+ }
283
295
  }
284
296
 
297
+ process.stderr.write("\n");
298
+
285
299
  const changes = [];
286
300
 
287
301
  // Check for modified and deleted files
288
302
  for (const [file, hash] of Object.entries(baseFiles)) {
289
303
  if (!(file in currentFiles)) {
290
- changes.push({ file, status: "D" });
304
+ changes.push({ file, status: "D", mtime: null });
291
305
  } else if (currentFiles[file] !== hash) {
292
- changes.push({ file, status: "M" });
306
+ const fullPath = path.join(resolvedProject, file.replace(/\//g, path.sep));
307
+ let mtime = null;
308
+
309
+ try {
310
+ const stat = await fs.promises.stat(fullPath);
311
+ mtime = stat.mtime;
312
+ } catch (_) {}
313
+
314
+ changes.push({ file, status: "M", mtime });
293
315
  }
294
316
  }
295
317
 
296
318
  // Check for new/untracked files
297
319
  for (const file of Object.keys(currentFiles)) {
298
320
  if (!(file in baseFiles)) {
299
- changes.push({ file, status: "U" });
321
+ const fullPath = path.join(resolvedProject, file.replace(/\//g, path.sep));
322
+ let mtime = null;
323
+
324
+ try {
325
+ const stat = await fs.promises.stat(fullPath);
326
+ mtime = stat.mtime;
327
+ } catch (_) {}
328
+
329
+ changes.push({ file, status: "U", mtime });
300
330
  }
301
331
  }
302
332
 
@@ -329,20 +359,23 @@ function sanitizeCsvCell(value) {
329
359
  return value;
330
360
  }
331
361
 
362
+ const STATUS_LABELS = { M: "Modified", U: "Untracked", D: "Deleted" };
363
+
332
364
  /**
333
365
  * Export changes to a CSV file.
334
366
  */
335
367
  async function exportCsv(changes, outputDir) {
336
368
  const csvPath = path.join(outputDir, "cwgit-changes.csv");
337
- const lines = ["file,status"];
369
+ const lines = ["file,status,date"];
338
370
 
339
- for (const { file, status } of changes) {
371
+ for (const { file, status, mtime } of changes) {
340
372
  const safeFile = sanitizeCsvCell(file);
341
- // Escape double quotes in file path and wrap in quotes if contains comma
342
373
  const escaped = safeFile.includes(",") || safeFile.includes('"')
343
374
  ? `"${safeFile.replace(/"/g, '""')}"`
344
375
  : safeFile;
345
- lines.push(`${escaped},${status}`);
376
+ const label = STATUS_LABELS[status] || status;
377
+ const date = mtime ? mtime.toISOString().replace("T", " ").slice(0, 19) : "";
378
+ lines.push(`${escaped},${label},${date}`);
346
379
  }
347
380
 
348
381
  await fs.promises.writeFile(csvPath, lines.join("\n") + "\n", "utf8");