Skip to content

Commit

Permalink
feat: watch specified reload files
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien-R44 committed Apr 1, 2024
1 parent 6dbf75f commit f4250e3
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ We have some examples in the examples folder with different frameworks to help y

- `reload`: An array of glob patterns that specifies which files should trigger a full process reload.
- `ignore`: An array of glob patterns that specifies which files should not be considered by Hot Hook. By default, ['**/node_modules/**'].
- `projectRoot`: The path of the project root folder.
- `projectRoot`: The path of the project root folder. Glob patterns are resolved relative to this path.

## API

Expand Down
1 change: 1 addition & 0 deletions packages/hot_hook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
},
"dependencies": {
"chokidar": "^3.6.0",
"fast-glob": "^3.3.2",
"picomatch": "^4.0.2"
},
"author": "Julien Ripouteau <[email protected]>",
Expand Down
14 changes: 9 additions & 5 deletions packages/hot_hook/src/loader.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import fg from 'fast-glob'
import chokidar from 'chokidar'
import picomatch from 'picomatch'
import { realpath } from 'node:fs/promises'
import { relative, resolve as pathResolve } from 'node:path'
import { MessagePort } from 'node:worker_threads'
import { relative, resolve as pathResolve } from 'node:path'
import type { InitializeHook, LoadHook, ResolveHook } from 'node:module'

import debug from './debug.js'
Expand All @@ -21,7 +22,7 @@ export class HotHookLoader {
this.#projectRoot = options.projectRoot
this.#messagePort = options.messagePort

this.#watcher = this.#createWatcher()
this.#watcher = this.#createWatcher(options.reload)
this.#isReloadPathMatcher = picomatch(options.reload || [])
this.#isPathIgnoredMatcher = picomatch(options.ignore || [])
}
Expand Down Expand Up @@ -71,8 +72,11 @@ export class HotHookLoader {
/**
* Create the chokidar watcher instance.
*/
#createWatcher() {
const watcher = chokidar.watch([])
#createWatcher(initialPaths: picomatch.Glob = []) {
const arrayPaths = Array.isArray(initialPaths) ? initialPaths : [initialPaths]
const entries = fg.sync(arrayPaths, { cwd: this.#projectRoot, absolute: true })

const watcher = chokidar.watch(entries)

watcher.on('change', this.#onFileChange.bind(this))
watcher.on('unlink', (relativeFilePath) => {
Expand Down Expand Up @@ -168,7 +172,7 @@ export class HotHookLoader {
}

let loader!: HotHookLoader
export const initialize: InitializeHook = (data: InitializeHookOptions) => {
export const initialize: InitializeHook = async (data: InitializeHookOptions) => {
loader = new HotHookLoader(data)
}
export const load: LoadHook = (...args) => loader?.load(...args)
Expand Down
3 changes: 3 additions & 0 deletions packages/hot_hook/tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export function runProcess(scriptPath: string, options?: NodeOptions) {
const child = execaNode(scriptPath, { nodeOptions: [], buffer: false, ...options })
activeTest.cleanup(() => void child.kill())

// child.stdout?.pipe(process.stdout)
// child.stderr?.pipe(process.stderr)

return {
child,
async waitForOutput(output: string, timeout = 10_000) {
Expand Down
50 changes: 50 additions & 0 deletions packages/hot_hook/tests/loader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,54 @@ test.group('Loader', () => {
await createHandlerFile({ path: 'node_modules/app/app.js', response: 'Hello World! Updated' })
await supertest('http://localhost:3333').get('/').expect(200).expect('Hello World!')
})

test('add reload paths to the watcher', async ({ fs, assert }) => {
await fakeInstall(fs.basePath)

await fs.createJson('package.json', { type: 'module' })
await fs.create('config/test.js', 'console.log("Hello")')
await fs.create('config/test2.js', 'console.log("Hello")')
await fs.create(
'server.js',
`import * as http from 'http'
import { hot } from 'hot-hook'
import { join } from 'node:path'
await hot.init({
projectRoot: join(import.meta.dirname, '.'),
reload: ['app.js', 'server.js', 'config/**/*'],
})
const server = http.createServer(async (request, response) => {
const app = await import('./app.js')
await app.default(request, response)
})
server.listen(3333, () => {
console.log('Server is running')
})`
)

await createHandlerFile({ path: 'app.js', response: 'Hello World!' })

const server = runProcess('server.js', {
cwd: fs.basePath,
env: { NODE_DEBUG: 'hot-hook' },
})

await server.waitForOutput('Server is running')
await fs.create('config/test.js', 'console.log("Hello Updated")')

await setTimeout(100)

const result = await pEvent(
server.child,
'message',
(message: any) =>
message?.type === 'hot-hook:full-reload' &&
message.path === join(fs.basePath, 'config/test.js')
)

assert.isDefined(result)
})
})
11 changes: 3 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f4250e3

Please sign in to comment.