Skip to content

Commit 88f5925

Browse files
authored
Merge pull request #7317 from Shopify/jf-on-error
add watcher error reporting in theme fs
2 parents 6ca0426 + a95ee0f commit 88f5925

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/theme': patch
3+
---
4+
5+
Add error handler to chokidar file watcher to prevent unhandled exceptions

packages/theme/src/cli/utilities/theme-fs.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {bulkUploadThemeAssets, deleteThemeAssets, fetchThemeAssets} from '@shopi
1818
import {renderError} from '@shopify/cli-kit/node/ui'
1919
import {Operation, type Checksum, type ThemeAsset} from '@shopify/cli-kit/node/themes/types'
2020
import {dirname, joinPath} from '@shopify/cli-kit/node/path'
21+
import {recordError} from '@shopify/cli-kit/node/analytics'
2122
import {AdminSession} from '@shopify/cli-kit/node/session'
2223

2324
import EventEmitter from 'events'
@@ -33,6 +34,13 @@ vi.mock('./asset-ignore.js')
3334
vi.mock('@shopify/cli-kit/node/themes/api')
3435
vi.mock('@shopify/cli-kit/node/ui')
3536
vi.mock('@shopify/cli-kit/node/output')
37+
vi.mock('@shopify/cli-kit/node/analytics', async (importOriginal) => {
38+
const actual = await importOriginal<typeof import('@shopify/cli-kit/node/analytics')>()
39+
return {
40+
...actual,
41+
recordError: vi.fn(),
42+
}
43+
})
3644
vi.mock('./theme-environment/hot-reload/server.js')
3745

3846
beforeEach(async () => {
@@ -851,6 +859,35 @@ describe('theme-fs', () => {
851859
})
852860
})
853861

862+
describe('watcher error handling', () => {
863+
const themeId = '123'
864+
const adminSession = {token: 'token'} as AdminSession
865+
const root = joinPath(locationOfThisFile, 'fixtures/theme')
866+
867+
beforeEach(() => {
868+
const mockWatcher = new EventEmitter()
869+
vi.spyOn(chokidar, 'watch').mockImplementation((_) => {
870+
return mockWatcher as any
871+
})
872+
})
873+
874+
test('outputs a warning when the watcher emits an error', async () => {
875+
// Given
876+
const {outputWarn} = await import('@shopify/cli-kit/node/output')
877+
const themeFileSystem = mountThemeFileSystem(root)
878+
await themeFileSystem.ready()
879+
await themeFileSystem.startWatcher(themeId, adminSession)
880+
881+
// When
882+
const watcher = chokidar.watch('') as EventEmitter
883+
watcher.emit('error', new Error('EMFILE: too many open files'))
884+
885+
// Then
886+
expect(outputWarn).toHaveBeenCalledWith('File watcher error: Error: EMFILE: too many open files')
887+
expect(recordError).toHaveBeenCalledWith('theme-service:file-watcher:error')
888+
})
889+
})
890+
854891
describe('handleSyncUpdate', () => {
855892
const fileKey = 'assets/test.css'
856893
const themeId = '123'

packages/theme/src/cli/utilities/theme-fs.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {joinPath, basename, relativePath} from '@shopify/cli-kit/node/path'
1010
import {lookupMimeType, setMimeTypes} from '@shopify/cli-kit/node/mimes'
1111
import {outputContent, outputDebug, outputInfo, outputToken, outputWarn} from '@shopify/cli-kit/node/output'
1212
import {buildThemeAsset} from '@shopify/cli-kit/node/themes/factories'
13+
import {recordError} from '@shopify/cli-kit/node/analytics'
1314
import {AdminSession} from '@shopify/cli-kit/node/session'
1415
import {bulkUploadThemeAssets, deleteThemeAssets} from '@shopify/cli-kit/node/themes/api'
1516

@@ -347,6 +348,10 @@ export function mountThemeFileSystem(root: string, options?: ThemeFileSystemOpti
347348
.on('add', queueFsEvent.bind(null, 'add'))
348349
.on('change', queueFsEvent.bind(null, 'change'))
349350
.on('unlink', queueFsEvent.bind(null, 'unlink'))
351+
.on('error', (error) => {
352+
outputWarn(`File watcher error: ${error}`)
353+
recordError('theme-service:file-watcher:error')
354+
})
350355
},
351356
}
352357
}

0 commit comments

Comments
 (0)