ts-repo-utils 7.8.1 → 7.9.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.
Files changed (73) hide show
  1. package/README.md +10 -0
  2. package/dist/cmd/assert-repo-is-clean.mjs +2 -1
  3. package/dist/cmd/assert-repo-is-clean.mjs.map +1 -1
  4. package/dist/cmd/check-should-run-type-checks.mjs +2 -1
  5. package/dist/cmd/check-should-run-type-checks.mjs.map +1 -1
  6. package/dist/cmd/format-diff-from.mjs +2 -1
  7. package/dist/cmd/format-diff-from.mjs.map +1 -1
  8. package/dist/cmd/format-uncommitted.mjs +2 -1
  9. package/dist/cmd/format-uncommitted.mjs.map +1 -1
  10. package/dist/cmd/gen-index-ts.mjs +2 -1
  11. package/dist/cmd/gen-index-ts.mjs.map +1 -1
  12. package/dist/entry-point.d.mts.map +1 -1
  13. package/dist/functions/assert-ext.d.mts +0 -1
  14. package/dist/functions/assert-ext.d.mts.map +1 -1
  15. package/dist/functions/assert-ext.mjs.map +1 -1
  16. package/dist/functions/assert-path-exists.d.mts.map +1 -1
  17. package/dist/functions/assert-path-exists.mjs.map +1 -1
  18. package/dist/functions/assert-repo-is-clean.d.mts.map +1 -1
  19. package/dist/functions/assert-repo-is-clean.mjs.map +1 -1
  20. package/dist/functions/create-result-assert.d.mts +0 -1
  21. package/dist/functions/create-result-assert.d.mts.map +1 -1
  22. package/dist/functions/create-result-assert.mjs.map +1 -1
  23. package/dist/functions/diff.d.mts +0 -1
  24. package/dist/functions/diff.d.mts.map +1 -1
  25. package/dist/functions/exec-async.d.mts +0 -1
  26. package/dist/functions/exec-async.d.mts.map +1 -1
  27. package/dist/functions/exec-async.mjs.map +1 -1
  28. package/dist/functions/format.d.mts +4 -5
  29. package/dist/functions/format.d.mts.map +1 -1
  30. package/dist/functions/format.mjs +3 -3
  31. package/dist/functions/format.mjs.map +1 -1
  32. package/dist/functions/gen-index.d.mts +0 -1
  33. package/dist/functions/gen-index.d.mts.map +1 -1
  34. package/dist/functions/gen-index.mjs.map +1 -1
  35. package/dist/functions/should-run.d.mts.map +1 -1
  36. package/dist/functions/should-run.mjs.map +1 -1
  37. package/dist/functions/workspace-utils/execute-parallel.d.mts.map +1 -1
  38. package/dist/functions/workspace-utils/execute-parallel.mjs +4 -5
  39. package/dist/functions/workspace-utils/execute-parallel.mjs.map +1 -1
  40. package/dist/functions/workspace-utils/get-workspace-packages.d.mts.map +1 -1
  41. package/dist/functions/workspace-utils/get-workspace-packages.mjs.map +1 -1
  42. package/dist/functions/workspace-utils/run-cmd-in-parallel.d.mts.map +1 -1
  43. package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs +2 -1
  44. package/dist/functions/workspace-utils/run-cmd-in-parallel.mjs.map +1 -1
  45. package/dist/functions/workspace-utils/run-cmd-in-stages.d.mts.map +1 -1
  46. package/dist/functions/workspace-utils/run-cmd-in-stages.mjs +2 -1
  47. package/dist/functions/workspace-utils/run-cmd-in-stages.mjs.map +1 -1
  48. package/dist/node-global.d.mts +0 -1
  49. package/dist/node-global.d.mts.map +1 -1
  50. package/package.json +25 -26
  51. package/src/cmd/assert-repo-is-clean.mts +2 -1
  52. package/src/cmd/check-should-run-type-checks.mts +2 -1
  53. package/src/cmd/format-diff-from.mts +2 -1
  54. package/src/cmd/format-uncommitted.mts +3 -1
  55. package/src/cmd/gen-index-ts.mts +8 -2
  56. package/src/entry-point.mts +1 -0
  57. package/src/functions/assert-ext.mts +4 -0
  58. package/src/functions/assert-path-exists.mts +2 -0
  59. package/src/functions/assert-repo-is-clean.mts +9 -0
  60. package/src/functions/create-result-assert.mts +1 -0
  61. package/src/functions/diff.test.mts +136 -8
  62. package/src/functions/exec-async.mts +4 -0
  63. package/src/functions/exec-async.test.mts +59 -2
  64. package/src/functions/format.mts +26 -7
  65. package/src/functions/format.test.mts +166 -9
  66. package/src/functions/gen-index.mts +16 -0
  67. package/src/functions/should-run.mts +2 -0
  68. package/src/functions/workspace-utils/execute-parallel.mts +27 -5
  69. package/src/functions/workspace-utils/get-workspace-packages.mts +5 -0
  70. package/src/functions/workspace-utils/run-cmd-in-parallel.mts +7 -1
  71. package/src/functions/workspace-utils/run-cmd-in-stages.mts +7 -1
  72. package/src/functions/workspace-utils/run-cmd-in-stages.test.mts +17 -3
  73. package/src/node-global.mts +7 -1
@@ -1,4 +1,3 @@
1
- /* eslint-disable vitest/no-conditional-expect */
2
1
  import dedent from 'dedent';
3
2
  import { Result } from 'ts-data-forge';
4
3
  import '../node-global.mjs';
@@ -15,14 +14,14 @@ import {
15
14
  formatUncommittedFiles,
16
15
  } from './format.mjs';
17
16
 
18
- vi.mock('./diff.mjs', () => ({
17
+ vi.mock(import('./diff.mjs'), () => ({
19
18
  getDiffFrom: vi.fn(),
20
19
  getModifiedFiles: vi.fn(),
21
20
  getStagedFiles: vi.fn(),
22
21
  getUntrackedFiles: vi.fn(),
23
22
  }));
24
23
 
25
- describe('formatFilesGlob', () => {
24
+ describe(formatFilesGlob, () => {
26
25
  const testDir = path.join(
27
26
  process.cwd(),
28
27
  `test-format-files-${crypto.randomUUID()}`,
@@ -34,7 +33,9 @@ describe('formatFilesGlob', () => {
34
33
  content: string,
35
34
  ): Promise<string> => {
36
35
  const filePath = path.join(testDir, filename);
36
+
37
37
  await fs.writeFile(filePath, content, 'utf8');
38
+
38
39
  return filePath;
39
40
  };
40
41
 
@@ -44,6 +45,7 @@ describe('formatFilesGlob', () => {
44
45
 
45
46
  test('should format files matching glob pattern', async () => {
46
47
  vi.clearAllMocks();
48
+
47
49
  // Setup test directory
48
50
  await fs.mkdir(testDir, { recursive: true });
49
51
 
@@ -71,10 +73,12 @@ describe('formatFilesGlob', () => {
71
73
 
72
74
  // Format TypeScript files
73
75
  const result = await formatFilesGlob(`${testDir}/*.ts`, { silent: true });
76
+
74
77
  expect(Result.isOk(result)).toBe(true);
75
78
 
76
79
  // Check that files were formatted
77
80
  const content1 = await readTestFile(file1);
81
+
78
82
  expect(content1).toBe(
79
83
  `${dedent`
80
84
  const foo = 'bar';
@@ -83,6 +87,7 @@ describe('formatFilesGlob', () => {
83
87
  );
84
88
 
85
89
  const content2 = await readTestFile(file2);
90
+
86
91
  expect(content2).toBe(
87
92
  `${dedent`
88
93
  function test(x: number, y: string) {
@@ -93,6 +98,7 @@ describe('formatFilesGlob', () => {
93
98
 
94
99
  // Check that non-matching file was not touched
95
100
  const mdContent = await readTestFile(path.join(testDir, 'test.md'));
101
+
96
102
  expect(mdContent).toBe('# Test\n\nSome spaces');
97
103
  } finally {
98
104
  // Cleanup
@@ -102,14 +108,17 @@ describe('formatFilesGlob', () => {
102
108
 
103
109
  test('should return ok when no files match pattern', async () => {
104
110
  vi.clearAllMocks();
111
+
105
112
  const result = await formatFilesGlob('/non-existent-path/*.ts', {
106
113
  silent: true,
107
114
  });
115
+
108
116
  expect(Result.isOk(result)).toBe(true);
109
117
  });
110
118
 
111
119
  test('should handle nested directories with glob pattern', async () => {
112
120
  vi.clearAllMocks();
121
+
113
122
  // Setup test directory with nested structure
114
123
  await fs.mkdir(path.join(testDir, 'src', 'utils'), { recursive: true });
115
124
 
@@ -126,10 +135,12 @@ describe('formatFilesGlob', () => {
126
135
  const result = await formatFilesGlob(`${testDir}/**/*.ts`, {
127
136
  silent: true,
128
137
  });
138
+
129
139
  expect(Result.isOk(result)).toBe(true);
130
140
 
131
141
  // Check that nested file was formatted
132
142
  const content = await readTestFile(nestedFile);
143
+
133
144
  expect(content).toBe(
134
145
  `${dedent`
135
146
  export const helper = (x: number) => {
@@ -144,7 +155,7 @@ describe('formatFilesGlob', () => {
144
155
  });
145
156
  });
146
157
 
147
- describe('formatFiles', () => {
158
+ describe(formatFiles, () => {
148
159
  const testDir = path.join(
149
160
  process.cwd(),
150
161
  `test-format-files-list-${crypto.randomUUID()}`,
@@ -156,7 +167,9 @@ describe('formatFiles', () => {
156
167
  content: string,
157
168
  ): Promise<string> => {
158
169
  const filePath = path.join(testDir, filename);
170
+
159
171
  await fs.writeFile(filePath, content, 'utf8');
172
+
160
173
  return filePath;
161
174
  };
162
175
 
@@ -166,6 +179,7 @@ describe('formatFiles', () => {
166
179
 
167
180
  test('should format a list of files', async () => {
168
181
  vi.clearAllMocks();
182
+
169
183
  await fs.mkdir(testDir, { recursive: true });
170
184
 
171
185
  try {
@@ -188,10 +202,12 @@ describe('formatFiles', () => {
188
202
  const result = await formatFiles([file1, file2], {
189
203
  silent: true,
190
204
  });
205
+
191
206
  expect(Result.isOk(result)).toBe(true);
192
207
 
193
208
  // Check formatted content
194
209
  const content1 = await readTestFile(file1);
210
+
195
211
  expect(content1).toBe(
196
212
  `${dedent`
197
213
  const x = { a: 1, b: 2 };
@@ -199,6 +215,7 @@ describe('formatFiles', () => {
199
215
  );
200
216
 
201
217
  const content2 = await readTestFile(file2);
218
+
202
219
  expect(content2).toBe(
203
220
  `${dedent`
204
221
  function test() {
@@ -213,14 +230,16 @@ describe('formatFiles', () => {
213
230
 
214
231
  test('should return ok for empty file list', async () => {
215
232
  vi.clearAllMocks();
233
+
216
234
  const result = await formatFiles([], {
217
235
  silent: true,
218
236
  });
237
+
219
238
  expect(Result.isOk(result)).toBe(true);
220
239
  });
221
240
  });
222
241
 
223
- describe('formatUncommittedFiles', () => {
242
+ describe(formatUncommittedFiles, () => {
224
243
  const testDir = path.join(
225
244
  process.cwd(),
226
245
  `test-format-uncommitted-${crypto.randomUUID()}`,
@@ -231,14 +250,19 @@ describe('formatUncommittedFiles', () => {
231
250
  content: string,
232
251
  ): Promise<string> => {
233
252
  const filePath = path.join(testDir, filename);
253
+
234
254
  const dir = path.dirname(filePath);
255
+
235
256
  await fs.mkdir(dir, { recursive: true });
257
+
236
258
  await fs.writeFile(filePath, content, 'utf8');
259
+
237
260
  return filePath;
238
261
  };
239
262
 
240
263
  const setupTest = async (): Promise<void> => {
241
264
  vi.clearAllMocks();
265
+
242
266
  await fs.mkdir(testDir, { recursive: true });
243
267
  };
244
268
 
@@ -248,42 +272,54 @@ describe('formatUncommittedFiles', () => {
248
272
 
249
273
  test('should format all uncommitted files by default', async () => {
250
274
  await setupTest();
275
+
251
276
  try {
252
277
  const untrackedFiles = ['untracked1.ts', 'untracked2.ts'];
278
+
253
279
  const modifiedFiles = ['modified1.ts', 'modified2.ts'];
280
+
254
281
  const stagedFiles = ['staged1.ts', 'staged2.ts'];
255
282
 
256
283
  // Create test files
257
284
  const allFiles = [...untrackedFiles, ...modifiedFiles, ...stagedFiles];
285
+
258
286
  const filePromises = allFiles.map((file) =>
259
287
  createTestFile(file, 'const x=1'),
260
288
  );
289
+
261
290
  await Promise.all(filePromises);
262
291
 
263
292
  // Mock git functions
264
293
  vi.mocked(getUntrackedFiles).mockResolvedValue(
265
294
  Result.ok(untrackedFiles.map((f) => path.join(testDir, f))),
266
295
  );
296
+
267
297
  vi.mocked(getModifiedFiles).mockResolvedValue(
268
298
  Result.ok(modifiedFiles.map((f) => path.join(testDir, f))),
269
299
  );
300
+
270
301
  vi.mocked(getStagedFiles).mockResolvedValue(
271
302
  Result.ok(stagedFiles.map((f) => path.join(testDir, f))),
272
303
  );
273
304
 
274
305
  const result = await formatUncommittedFiles({ silent: true });
306
+
275
307
  expect(Result.isOk(result)).toBe(true);
276
308
 
277
309
  // Verify all git functions were called
278
310
  expect(getUntrackedFiles).toHaveBeenCalledWith({ silent: true });
311
+
279
312
  expect(getModifiedFiles).toHaveBeenCalledWith({ silent: true });
313
+
280
314
  expect(getStagedFiles).toHaveBeenCalledWith({ silent: true });
281
315
 
282
316
  // Verify files were formatted
283
317
  const verifyPromises = allFiles.map(async (file) => {
284
318
  const content = await fs.readFile(path.join(testDir, file), 'utf8');
319
+
285
320
  expect(content).toBe('const x = 1;\n');
286
321
  });
322
+
287
323
  await Promise.all(verifyPromises);
288
324
  } finally {
289
325
  await cleanupTest();
@@ -292,8 +328,10 @@ describe('formatUncommittedFiles', () => {
292
328
 
293
329
  test('should format only untracked files when specified', async () => {
294
330
  await setupTest();
331
+
295
332
  try {
296
333
  const untrackedFiles = ['untracked.ts'] as const;
334
+
297
335
  await createTestFile(untrackedFiles[0], 'const x=1');
298
336
 
299
337
  vi.mocked(getUntrackedFiles).mockResolvedValue(
@@ -306,10 +344,13 @@ describe('formatUncommittedFiles', () => {
306
344
  staged: false,
307
345
  silent: true,
308
346
  });
347
+
309
348
  expect(Result.isOk(result)).toBe(true);
310
349
 
311
350
  expect(getUntrackedFiles).toHaveBeenCalledWith({ silent: true });
351
+
312
352
  expect(getModifiedFiles).not.toHaveBeenCalled();
353
+
313
354
  expect(getStagedFiles).not.toHaveBeenCalled();
314
355
  } finally {
315
356
  await cleanupTest();
@@ -318,8 +359,10 @@ describe('formatUncommittedFiles', () => {
318
359
 
319
360
  test('should format only modified files when specified', async () => {
320
361
  await setupTest();
362
+
321
363
  try {
322
364
  const modifiedFiles = ['modified.ts'] as const;
365
+
323
366
  await createTestFile(modifiedFiles[0], 'const x=1');
324
367
 
325
368
  vi.mocked(getModifiedFiles).mockResolvedValue(
@@ -332,10 +375,13 @@ describe('formatUncommittedFiles', () => {
332
375
  staged: false,
333
376
  silent: true,
334
377
  });
378
+
335
379
  expect(Result.isOk(result)).toBe(true);
336
380
 
337
381
  expect(getUntrackedFiles).not.toHaveBeenCalled();
382
+
338
383
  expect(getModifiedFiles).toHaveBeenCalledWith({ silent: true });
384
+
339
385
  expect(getStagedFiles).not.toHaveBeenCalled();
340
386
  } finally {
341
387
  await cleanupTest();
@@ -344,8 +390,10 @@ describe('formatUncommittedFiles', () => {
344
390
 
345
391
  test('should format only staged files when specified', async () => {
346
392
  await setupTest();
393
+
347
394
  try {
348
395
  const stagedFiles = ['staged.ts'] as const;
396
+
349
397
  await createTestFile(stagedFiles[0], 'const x=1');
350
398
 
351
399
  vi.mocked(getStagedFiles).mockResolvedValue(
@@ -358,10 +406,13 @@ describe('formatUncommittedFiles', () => {
358
406
  staged: true,
359
407
  silent: true,
360
408
  });
409
+
361
410
  expect(Result.isOk(result)).toBe(true);
362
411
 
363
412
  expect(getUntrackedFiles).not.toHaveBeenCalled();
413
+
364
414
  expect(getModifiedFiles).not.toHaveBeenCalled();
415
+
365
416
  expect(getStagedFiles).toHaveBeenCalledWith({ silent: true });
366
417
  } finally {
367
418
  await cleanupTest();
@@ -370,19 +421,24 @@ describe('formatUncommittedFiles', () => {
370
421
 
371
422
  test('should handle combinations of file types', async () => {
372
423
  await setupTest();
424
+
373
425
  try {
374
426
  const untrackedFiles = ['untracked.ts'];
427
+
375
428
  const stagedFiles = ['staged.ts'];
376
429
 
377
430
  const allFiles = [...untrackedFiles, ...stagedFiles];
431
+
378
432
  const filePromises = allFiles.map((file) =>
379
433
  createTestFile(file, 'const x=1'),
380
434
  );
435
+
381
436
  await Promise.all(filePromises);
382
437
 
383
438
  vi.mocked(getUntrackedFiles).mockResolvedValue(
384
439
  Result.ok(untrackedFiles.map((f) => path.join(testDir, f))),
385
440
  );
441
+
386
442
  vi.mocked(getStagedFiles).mockResolvedValue(
387
443
  Result.ok(stagedFiles.map((f) => path.join(testDir, f))),
388
444
  );
@@ -393,10 +449,13 @@ describe('formatUncommittedFiles', () => {
393
449
  staged: true,
394
450
  silent: true,
395
451
  });
452
+
396
453
  expect(Result.isOk(result)).toBe(true);
397
454
 
398
455
  expect(getUntrackedFiles).toHaveBeenCalledWith({ silent: true });
456
+
399
457
  expect(getModifiedFiles).not.toHaveBeenCalled();
458
+
400
459
  expect(getStagedFiles).toHaveBeenCalledWith({ silent: true });
401
460
  } finally {
402
461
  await cleanupTest();
@@ -405,22 +464,28 @@ describe('formatUncommittedFiles', () => {
405
464
 
406
465
  test('should deduplicate files that appear in multiple categories', async () => {
407
466
  await setupTest();
467
+
408
468
  try {
409
469
  const duplicateFile = path.join(testDir, 'duplicate.ts');
470
+
410
471
  await createTestFile('duplicate.ts', 'const x=1');
411
472
 
412
473
  // Mock the same file appearing in multiple categories
413
474
  vi.mocked(getUntrackedFiles).mockResolvedValue(
414
475
  Result.ok([duplicateFile]),
415
476
  );
477
+
416
478
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([duplicateFile]));
479
+
417
480
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([duplicateFile]));
418
481
 
419
482
  const result = await formatUncommittedFiles({ silent: true });
483
+
420
484
  expect(Result.isOk(result)).toBe(true);
421
485
 
422
486
  // Verify file was formatted (only once despite appearing in all categories)
423
487
  const content = await fs.readFile(duplicateFile, 'utf8');
488
+
424
489
  expect(content).toBe('const x = 1;\n');
425
490
  } finally {
426
491
  await cleanupTest();
@@ -429,12 +494,16 @@ describe('formatUncommittedFiles', () => {
429
494
 
430
495
  test('should handle empty file lists', async () => {
431
496
  await setupTest();
497
+
432
498
  try {
433
499
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([]));
500
+
434
501
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
502
+
435
503
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
436
504
 
437
505
  const result = await formatUncommittedFiles({ silent: true });
506
+
438
507
  expect(Result.isOk(result)).toBe(true);
439
508
  } finally {
440
509
  await cleanupTest();
@@ -443,8 +512,10 @@ describe('formatUncommittedFiles', () => {
443
512
 
444
513
  test('should return error when getUntrackedFiles fails', async () => {
445
514
  await setupTest();
515
+
446
516
  try {
447
517
  const error = { message: 'Git error' };
518
+
448
519
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.err(error));
449
520
 
450
521
  const result = await formatUncommittedFiles({
@@ -453,9 +524,11 @@ describe('formatUncommittedFiles', () => {
453
524
  staged: false,
454
525
  silent: true,
455
526
  });
527
+
456
528
  expect(Result.isErr(result)).toBe(true);
529
+
457
530
  if (Result.isErr(result)) {
458
- expect(result.value).toStrictEqual(error);
531
+ assert.deepStrictEqual(result.value, error);
459
532
  }
460
533
  } finally {
461
534
  await cleanupTest();
@@ -464,8 +537,10 @@ describe('formatUncommittedFiles', () => {
464
537
 
465
538
  test('should return error when getModifiedFiles fails', async () => {
466
539
  await setupTest();
540
+
467
541
  try {
468
542
  const error = { message: 'Git error' };
543
+
469
544
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.err(error));
470
545
 
471
546
  const result = await formatUncommittedFiles({
@@ -474,9 +549,11 @@ describe('formatUncommittedFiles', () => {
474
549
  staged: false,
475
550
  silent: true,
476
551
  });
552
+
477
553
  expect(Result.isErr(result)).toBe(true);
554
+
478
555
  if (Result.isErr(result)) {
479
- expect(result.value).toStrictEqual(error);
556
+ assert.deepStrictEqual(result.value, error);
480
557
  }
481
558
  } finally {
482
559
  await cleanupTest();
@@ -485,8 +562,10 @@ describe('formatUncommittedFiles', () => {
485
562
 
486
563
  test('should return error when getStagedFiles fails', async () => {
487
564
  await setupTest();
565
+
488
566
  try {
489
567
  const error = { message: 'Git error' };
568
+
490
569
  vi.mocked(getStagedFiles).mockResolvedValue(Result.err(error));
491
570
 
492
571
  const result = await formatUncommittedFiles({
@@ -495,9 +574,11 @@ describe('formatUncommittedFiles', () => {
495
574
  staged: true,
496
575
  silent: true,
497
576
  });
577
+
498
578
  expect(Result.isErr(result)).toBe(true);
579
+
499
580
  if (Result.isErr(result)) {
500
- expect(result.value).toStrictEqual(error);
581
+ assert.deepStrictEqual(result.value, error);
501
582
  }
502
583
  } finally {
503
584
  await cleanupTest();
@@ -506,23 +587,29 @@ describe('formatUncommittedFiles', () => {
506
587
 
507
588
  test('should respect silent option', async () => {
508
589
  await setupTest();
590
+
509
591
  try {
510
592
  // Using vi.stubGlobal to avoid direct assignment
511
593
  const consoleErrorStub = vi.fn();
594
+
512
595
  vi.stubGlobal('console', {
513
596
  ...console,
514
597
  error: consoleErrorStub,
515
598
  });
516
599
 
517
600
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([]));
601
+
518
602
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
603
+
519
604
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
520
605
 
521
606
  const result1 = await formatUncommittedFiles({ silent: false });
607
+
522
608
  expect(Result.isOk(result1)).toBe(true);
523
609
  // With silent: false, console output may occur
524
610
 
525
611
  const result2 = await formatUncommittedFiles({ silent: true });
612
+
526
613
  expect(Result.isOk(result2)).toBe(true);
527
614
  // With silent: true, console output should be suppressed
528
615
 
@@ -534,8 +621,10 @@ describe('formatUncommittedFiles', () => {
534
621
 
535
622
  test('should format TypeScript files correctly', async () => {
536
623
  await setupTest();
624
+
537
625
  try {
538
626
  const testFile = 'test.ts';
627
+
539
628
  await createTestFile(
540
629
  testFile,
541
630
  dedent`
@@ -547,13 +636,17 @@ describe('formatUncommittedFiles', () => {
547
636
  vi.mocked(getUntrackedFiles).mockResolvedValue(
548
637
  Result.ok([path.join(testDir, testFile)]),
549
638
  );
639
+
550
640
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
641
+
551
642
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
552
643
 
553
644
  const result = await formatUncommittedFiles({ silent: true });
645
+
554
646
  expect(Result.isOk(result)).toBe(true);
555
647
 
556
648
  const content = await fs.readFile(path.join(testDir, testFile), 'utf8');
649
+
557
650
  expect(content).toBe(
558
651
  `${dedent`
559
652
  function test() {
@@ -569,19 +662,25 @@ describe('formatUncommittedFiles', () => {
569
662
 
570
663
  test('should handle non-formattable files gracefully', async () => {
571
664
  await setupTest();
665
+
572
666
  try {
573
667
  const binaryFile = 'test.bin';
668
+
574
669
  const binaryPath = path.join(testDir, binaryFile);
670
+
575
671
  await createTestFile(
576
672
  binaryFile,
577
673
  Buffer.from([0x00, 0x01, 0x02]).toString(),
578
674
  );
579
675
 
580
676
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([binaryPath]));
677
+
581
678
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
679
+
582
680
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
583
681
 
584
682
  const result = await formatUncommittedFiles({ silent: true });
683
+
585
684
  // Should handle error gracefully
586
685
  expect(Result.isOk(result) || Result.isErr(result)).toBe(true);
587
686
  } finally {
@@ -590,7 +689,7 @@ describe('formatUncommittedFiles', () => {
590
689
  });
591
690
  });
592
691
 
593
- describe('formatDiffFrom', () => {
692
+ describe(formatDiffFrom, () => {
594
693
  const testDir = path.join(
595
694
  process.cwd(),
596
695
  `test-format-diff-${crypto.randomUUID()}`,
@@ -601,7 +700,9 @@ describe('formatDiffFrom', () => {
601
700
  content: string,
602
701
  ): Promise<string> => {
603
702
  const filePath = path.join(testDir, filename);
703
+
604
704
  await fs.writeFile(filePath, content, 'utf8');
705
+
605
706
  return filePath;
606
707
  };
607
708
 
@@ -610,6 +711,7 @@ describe('formatDiffFrom', () => {
610
711
 
611
712
  test('should format files from diff', async () => {
612
713
  vi.clearAllMocks();
714
+
613
715
  await fs.mkdir(testDir, { recursive: true });
614
716
 
615
717
  try {
@@ -624,14 +726,18 @@ describe('formatDiffFrom', () => {
624
726
  vi.mocked(getDiffFrom).mockResolvedValue(Result.ok([file1]));
625
727
 
626
728
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([]));
729
+
627
730
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
731
+
628
732
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
629
733
 
630
734
  const result = await formatDiffFrom('main', { silent: true });
735
+
631
736
  expect(Result.isOk(result)).toBe(true);
632
737
 
633
738
  // Check file was formatted
634
739
  const content = await readTestFile(file1);
740
+
635
741
  expect(content).toBe(
636
742
  `${dedent`
637
743
  const a = 1;
@@ -647,6 +753,7 @@ describe('formatDiffFrom', () => {
647
753
 
648
754
  test('should include untracked files when option is set', async () => {
649
755
  vi.clearAllMocks();
756
+
650
757
  await fs.mkdir(testDir, { recursive: true });
651
758
 
652
759
  try {
@@ -666,20 +773,25 @@ describe('formatDiffFrom', () => {
666
773
 
667
774
  // Mock both functions
668
775
  vi.mocked(getDiffFrom).mockResolvedValue(Result.ok([diffFile]));
776
+
669
777
  vi.mocked(getUntrackedFiles).mockResolvedValue(
670
778
  Result.ok([untrackedFile]),
671
779
  );
780
+
672
781
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
782
+
673
783
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
674
784
 
675
785
  const result = await formatDiffFrom('main', {
676
786
  includeUntracked: true,
677
787
  silent: true,
678
788
  });
789
+
679
790
  expect(Result.isOk(result)).toBe(true);
680
791
 
681
792
  // Check both files were formatted
682
793
  const diffContent = await readTestFile(diffFile);
794
+
683
795
  expect(diffContent).toBe(
684
796
  `${dedent`
685
797
  const diff = true;
@@ -687,6 +799,7 @@ describe('formatDiffFrom', () => {
687
799
  );
688
800
 
689
801
  const untrackedContent = await readTestFile(untrackedFile);
802
+
690
803
  expect(untrackedContent).toBe(
691
804
  `${dedent`
692
805
  const untracked = true;
@@ -694,6 +807,7 @@ describe('formatDiffFrom', () => {
694
807
  );
695
808
 
696
809
  expect(getDiffFrom).toHaveBeenCalledWith('main', { silent: true });
810
+
697
811
  expect(getUntrackedFiles).toHaveBeenCalledWith({ silent: true });
698
812
  } finally {
699
813
  await fs.rm(testDir, { recursive: true, force: true });
@@ -702,6 +816,7 @@ describe('formatDiffFrom', () => {
702
816
 
703
817
  test('should deduplicate files when including untracked', async () => {
704
818
  vi.clearAllMocks();
819
+
705
820
  await fs.mkdir(testDir, { recursive: true });
706
821
 
707
822
  try {
@@ -714,22 +829,28 @@ describe('formatDiffFrom', () => {
714
829
 
715
830
  // Mock both functions to return the same file
716
831
  vi.mocked(getDiffFrom).mockResolvedValue(Result.ok([sharedFile]));
832
+
717
833
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([sharedFile]));
834
+
718
835
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
836
+
719
837
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
720
838
 
721
839
  const result = await formatDiffFrom('main', {
722
840
  includeUntracked: true,
723
841
  silent: true,
724
842
  });
843
+
725
844
  expect(Result.isOk(result)).toBe(true);
726
845
 
727
846
  // Verify both functions were called
728
847
  expect(getDiffFrom).toHaveBeenCalledWith('main', { silent: true });
848
+
729
849
  expect(getUntrackedFiles).toHaveBeenCalledWith({ silent: true });
730
850
 
731
851
  // Check that the file was formatted (content should change)
732
852
  const finalContent = await readTestFile(sharedFile);
853
+
733
854
  expect(finalContent).toBe(
734
855
  `${dedent`
735
856
  const shared = { value: 1 };
@@ -742,6 +863,7 @@ describe('formatDiffFrom', () => {
742
863
 
743
864
  test('should include both staged and untracked files by default', async () => {
744
865
  vi.clearAllMocks();
866
+
745
867
  await fs.mkdir(testDir, { recursive: true });
746
868
 
747
869
  try {
@@ -768,18 +890,23 @@ describe('formatDiffFrom', () => {
768
890
 
769
891
  // Mock all functions
770
892
  vi.mocked(getDiffFrom).mockResolvedValue(Result.ok([diffFile]));
893
+
771
894
  vi.mocked(getUntrackedFiles).mockResolvedValue(
772
895
  Result.ok([untrackedFile]),
773
896
  );
897
+
774
898
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
899
+
775
900
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([stagedFile]));
776
901
 
777
902
  // Test default behavior (no options provided)
778
903
  const result = await formatDiffFrom('main', { silent: true });
904
+
779
905
  expect(Result.isOk(result)).toBe(true);
780
906
 
781
907
  // Check all files were formatted
782
908
  const diffContent = await readTestFile(diffFile);
909
+
783
910
  expect(diffContent).toBe(
784
911
  `${dedent`
785
912
  const diff = true;
@@ -787,6 +914,7 @@ describe('formatDiffFrom', () => {
787
914
  );
788
915
 
789
916
  const stagedContent = await readTestFile(stagedFile);
917
+
790
918
  expect(stagedContent).toBe(
791
919
  `${dedent`
792
920
  const staged = true;
@@ -794,6 +922,7 @@ describe('formatDiffFrom', () => {
794
922
  );
795
923
 
796
924
  const untrackedContent = await readTestFile(untrackedFile);
925
+
797
926
  expect(untrackedContent).toBe(
798
927
  `${dedent`
799
928
  const untracked = true;
@@ -802,7 +931,9 @@ describe('formatDiffFrom', () => {
802
931
 
803
932
  // Verify all functions were called by default
804
933
  expect(getDiffFrom).toHaveBeenCalledWith('main', { silent: true });
934
+
805
935
  expect(getStagedFiles).toHaveBeenCalledWith({ silent: true });
936
+
806
937
  expect(getUntrackedFiles).toHaveBeenCalledWith({ silent: true });
807
938
  } finally {
808
939
  await fs.rm(testDir, { recursive: true, force: true });
@@ -811,6 +942,7 @@ describe('formatDiffFrom', () => {
811
942
 
812
943
  test('should include staged files when option is set', async () => {
813
944
  vi.clearAllMocks();
945
+
814
946
  await fs.mkdir(testDir, { recursive: true });
815
947
 
816
948
  try {
@@ -830,8 +962,11 @@ describe('formatDiffFrom', () => {
830
962
 
831
963
  // Mock all functions
832
964
  vi.mocked(getDiffFrom).mockResolvedValue(Result.ok([diffFile]));
965
+
833
966
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([]));
967
+
834
968
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
969
+
835
970
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([stagedFile]));
836
971
 
837
972
  const result = await formatDiffFrom('main', {
@@ -840,10 +975,12 @@ describe('formatDiffFrom', () => {
840
975
  includeModified: false,
841
976
  silent: true,
842
977
  });
978
+
843
979
  expect(Result.isOk(result)).toBe(true);
844
980
 
845
981
  // Check both files were formatted
846
982
  const diffContent = await readTestFile(diffFile);
983
+
847
984
  expect(diffContent).toBe(
848
985
  `${dedent`
849
986
  const diff = true;
@@ -851,6 +988,7 @@ describe('formatDiffFrom', () => {
851
988
  );
852
989
 
853
990
  const stagedContent = await readTestFile(stagedFile);
991
+
854
992
  expect(stagedContent).toBe(
855
993
  `${dedent`
856
994
  const staged = true;
@@ -858,7 +996,9 @@ describe('formatDiffFrom', () => {
858
996
  );
859
997
 
860
998
  expect(getDiffFrom).toHaveBeenCalledWith('main', { silent: true });
999
+
861
1000
  expect(getStagedFiles).toHaveBeenCalledWith({ silent: true });
1001
+
862
1002
  expect(getUntrackedFiles).not.toHaveBeenCalled();
863
1003
  } finally {
864
1004
  await fs.rm(testDir, { recursive: true, force: true });
@@ -867,6 +1007,7 @@ describe('formatDiffFrom', () => {
867
1007
 
868
1008
  test('should deduplicate files when including both staged and untracked', async () => {
869
1009
  vi.clearAllMocks();
1010
+
870
1011
  await fs.mkdir(testDir, { recursive: true });
871
1012
 
872
1013
  try {
@@ -879,8 +1020,11 @@ describe('formatDiffFrom', () => {
879
1020
 
880
1021
  // Mock all functions to return the same file
881
1022
  vi.mocked(getDiffFrom).mockResolvedValue(Result.ok([sharedFile]));
1023
+
882
1024
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([sharedFile]));
1025
+
883
1026
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
1027
+
884
1028
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([sharedFile]));
885
1029
 
886
1030
  const result = await formatDiffFrom('main', {
@@ -888,15 +1032,19 @@ describe('formatDiffFrom', () => {
888
1032
  includeStaged: true,
889
1033
  silent: true,
890
1034
  });
1035
+
891
1036
  expect(Result.isOk(result)).toBe(true);
892
1037
 
893
1038
  // Verify all functions were called
894
1039
  expect(getDiffFrom).toHaveBeenCalledWith('main', { silent: true });
1040
+
895
1041
  expect(getUntrackedFiles).toHaveBeenCalledWith({ silent: true });
1042
+
896
1043
  expect(getStagedFiles).toHaveBeenCalledWith({ silent: true });
897
1044
 
898
1045
  // Check that the file was formatted (content should change)
899
1046
  const finalContent = await readTestFile(sharedFile);
1047
+
900
1048
  expect(finalContent).toBe(
901
1049
  `${dedent`
902
1050
  const shared = { value: 1 };
@@ -909,6 +1057,7 @@ describe('formatDiffFrom', () => {
909
1057
 
910
1058
  test('should exclude staged files when option is set to false', async () => {
911
1059
  vi.clearAllMocks();
1060
+
912
1061
  await fs.mkdir(testDir, { recursive: true });
913
1062
 
914
1063
  try {
@@ -921,8 +1070,11 @@ describe('formatDiffFrom', () => {
921
1070
 
922
1071
  // Mock functions - staged should not be called
923
1072
  vi.mocked(getDiffFrom).mockResolvedValue(Result.ok([diffFile]));
1073
+
924
1074
  vi.mocked(getUntrackedFiles).mockResolvedValue(Result.ok([]));
1075
+
925
1076
  vi.mocked(getModifiedFiles).mockResolvedValue(Result.ok([]));
1077
+
926
1078
  vi.mocked(getStagedFiles).mockResolvedValue(Result.ok([]));
927
1079
 
928
1080
  const result = await formatDiffFrom('main', {
@@ -931,10 +1083,12 @@ describe('formatDiffFrom', () => {
931
1083
  includeModified: false,
932
1084
  silent: true,
933
1085
  });
1086
+
934
1087
  expect(Result.isOk(result)).toBe(true);
935
1088
 
936
1089
  // Check only diff file was formatted
937
1090
  const diffContent = await readTestFile(diffFile);
1091
+
938
1092
  expect(diffContent).toBe(
939
1093
  `${dedent`
940
1094
  const diff = true;
@@ -942,8 +1096,11 @@ describe('formatDiffFrom', () => {
942
1096
  );
943
1097
 
944
1098
  expect(getDiffFrom).toHaveBeenCalledWith('main', { silent: true });
1099
+
945
1100
  expect(getStagedFiles).not.toHaveBeenCalled();
1101
+
946
1102
  expect(getUntrackedFiles).not.toHaveBeenCalled();
1103
+
947
1104
  expect(getModifiedFiles).not.toHaveBeenCalled();
948
1105
  } finally {
949
1106
  await fs.rm(testDir, { recursive: true, force: true });