Skip to content

Commit 4df42ed

Browse files
committed
fix: Stop logging cache warnings when the Tailwind class cache file is missing so repeated builds on Windows no longer show ENOENT errors.
1 parent e5c8155 commit 4df42ed

3 files changed

Lines changed: 77 additions & 1 deletion

File tree

.changeset/quiet-cache-enoent.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'tailwindcss-patch': patch
3+
---
4+
5+
Stop logging cache warnings when the Tailwind class cache file is missing so repeated builds on Windows no longer show ENOENT errors.

packages/tailwindcss-patch/src/cache/store.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import type { NormalizedCacheOptions } from '../options/types'
22
import fs from 'fs-extra'
33
import logger from '../logger'
44

5+
function isErrnoException(error: unknown): error is NodeJS.ErrnoException {
6+
return error instanceof Error && typeof (error as NodeJS.ErrnoException).code === 'string'
7+
}
8+
59
export class CacheStore {
610
constructor(private readonly options: NormalizedCacheOptions) {}
711

@@ -62,6 +66,10 @@ export class CacheStore {
6266
}
6367
}
6468
catch (error) {
69+
if (isErrnoException(error) && error.code === 'ENOENT') {
70+
return new Set()
71+
}
72+
6573
logger.warn('Unable to read Tailwind class cache, removing invalid file.', error)
6674
try {
6775
await fs.remove(this.options.path)
@@ -91,6 +99,10 @@ export class CacheStore {
9199
}
92100
}
93101
catch (error) {
102+
if (isErrnoException(error) && error.code === 'ENOENT') {
103+
return new Set()
104+
}
105+
94106
logger.warn('Unable to read Tailwind class cache, removing invalid file.', error)
95107
try {
96108
fs.removeSync(this.options.path)

packages/tailwindcss-patch/test/cache.store.test.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import os from 'node:os'
22
import fs from 'fs-extra'
33
import path from 'pathe'
4-
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
4+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
55
import { CacheStore } from '@/cache/store'
6+
import logger from '@/logger'
67

78
let tempDir: string
89

@@ -74,4 +75,62 @@ describe('CacheStore', () => {
7475
expect(restored.size).toBe(1)
7576
expect(restored.has('foo')).toBe(true)
7677
})
78+
79+
it('ignores ENOENT errors while reading cache files', async () => {
80+
const cachePath = path.join(tempDir, 'cache.json')
81+
const store = new CacheStore({
82+
enabled: true,
83+
cwd: tempDir,
84+
dir: tempDir,
85+
file: 'cache.json',
86+
path: cachePath,
87+
strategy: 'merge',
88+
})
89+
90+
const warnSpy = vi.spyOn(logger, 'warn')
91+
const removeSpy = vi.spyOn(fs, 'remove')
92+
const pathExistsSpy = vi.spyOn(fs, 'pathExists').mockResolvedValue(true)
93+
const enoentError = Object.assign(new Error('missing'), { code: 'ENOENT' as NodeJS.ErrnoException['code'] })
94+
const readSpy = vi.spyOn(fs, 'readJSON').mockRejectedValue(enoentError)
95+
96+
const restored = await store.read()
97+
expect(restored.size).toBe(0)
98+
expect(warnSpy).not.toHaveBeenCalled()
99+
expect(removeSpy).not.toHaveBeenCalled()
100+
101+
warnSpy.mockRestore()
102+
removeSpy.mockRestore()
103+
pathExistsSpy.mockRestore()
104+
readSpy.mockRestore()
105+
})
106+
107+
it('ignores ENOENT errors while reading cache files synchronously', () => {
108+
const cachePath = path.join(tempDir, 'cache.json')
109+
const store = new CacheStore({
110+
enabled: true,
111+
cwd: tempDir,
112+
dir: tempDir,
113+
file: 'cache.json',
114+
path: cachePath,
115+
strategy: 'merge',
116+
})
117+
118+
const warnSpy = vi.spyOn(logger, 'warn')
119+
const removeSpy = vi.spyOn(fs, 'removeSync')
120+
const pathExistsSpy = vi.spyOn(fs, 'pathExistsSync').mockReturnValue(true)
121+
const enoentError = Object.assign(new Error('missing'), { code: 'ENOENT' as NodeJS.ErrnoException['code'] })
122+
const readSpy = vi.spyOn(fs, 'readJSONSync').mockImplementation(() => {
123+
throw enoentError
124+
})
125+
126+
const restored = store.readSync()
127+
expect(restored.size).toBe(0)
128+
expect(warnSpy).not.toHaveBeenCalled()
129+
expect(removeSpy).not.toHaveBeenCalled()
130+
131+
warnSpy.mockRestore()
132+
removeSpy.mockRestore()
133+
pathExistsSpy.mockRestore()
134+
readSpy.mockRestore()
135+
})
77136
})

0 commit comments

Comments
 (0)