Skip to content

Commit

Permalink
fix(server) bud.watch (#1007)
Browse files Browse the repository at this point in the history
  • Loading branch information
kellymears committed Jan 25, 2022
1 parent 94a208a commit 582c3f3
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 61 deletions.
15 changes: 13 additions & 2 deletions sources/@roots/bud-api/src/api/facade/facade.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,14 +684,25 @@ export class Facade {
public use: use.facade

/**
* Configure the list of files that, when modified,
* will force the browser to reload (even in hot mode).
* Set files that, when modified, will force the browser to reload.
*
* @remarks
* Modifying these files will cause a full page reload, even in hot mode.
*
* @example
* ```js
* app.watch(['templates/*.html'])
* ```
*
* @example
* Set chokidar options as well:
*
* ```js
* app.watch(['templates/*.html'], {
* // chokidar options
* })
* ```
*
* @public
*/
public watch: watch
Expand Down
50 changes: 31 additions & 19 deletions sources/@roots/bud-api/src/api/methods/watch/index.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,42 @@
import type {Framework, Server} from '@roots/bud-framework'
import {chalk} from '@roots/bud-support'

export interface watch {
(files: Server.Configuration['watch']['files']): Framework
(
files: Server.Configuration['watch']['files'],
options?: Server.Configuration['watch']['options'],
): Framework
}

export const watch: watch = function (files) {
/**
* Set files that, when modified, will force the browser to reload.
*
* @remarks
* Modifying these files will cause a full page reload, even in hot mode.
*
* @example
* ```js
* app.watch(['templates/*.html'])
* ```
*
* @example
* Set chokidar options as well:
*
* ```js
* app.watch(['templates/*.html'], {
* // chokidar options
* })
* ```
*
* @public
*/
export const watch: watch = function (files, options = {}) {
const ctx = (this.root as Framework) ?? (this as Framework)

if (!ctx.isDevelopment) {
ctx.api.log('log', {
message: 'skipping watch files',
suffix: 'production mode is set',
})
return ctx
}
files = Array.isArray(files) ? files : [files]

ctx.store.set(
'server.watch.files',
Array.isArray(files) ? files : [files],
)

ctx.api.log('success', {
message: `watch files added`,
suffix: chalk.dim(files.join(', ')),
})
ctx.store
.merge('server.watch.files', files)
.merge('server.watch.options', options)

return ctx
}
1 change: 1 addition & 0 deletions sources/@roots/bud-framework/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@types/js-yaml": "4.0.5",
"@types/lodash": "4.14.178",
"@types/node": "16.11.19",
"chokidar": "^3.5.3",
"http-proxy-middleware": "2.0.1",
"ink": "3.2.0",
"webpack": "5.65.0"
Expand Down
8 changes: 8 additions & 0 deletions sources/@roots/bud-framework/src/Server/Config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {WatchOptions} from 'chokidar'
import {URL} from 'url'

/**
Expand Down Expand Up @@ -39,6 +40,13 @@ export interface Configuration {
* @public
*/
files: Array<string>

/**
* Watch options
*
* @public
*/
options: WatchOptions
}

/**
Expand Down
1 change: 1 addition & 0 deletions sources/@roots/bud-framework/src/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ export namespace Store {
['server.middleware']: Repository['server']['middleware']
['server.browser']: Repository['server']['browser']
['server.watch.files']: Repository['server']['watch']['files']
['server.watch.options']: Repository['server']['watch']['options']
['server.middleware.dev']: Repository['server']['middleware']['dev']
['server.middleware.hot']: Repository['server']['middleware']['hot']
['server.middleware.proxy']: Repository['server']['middleware']['proxy']
Expand Down
67 changes: 40 additions & 27 deletions sources/@roots/bud-server/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class Server
*
* @public
*/
public middleware: Framework.Server.Middleware
public middleware: Framework.Server.Middleware = {}

/**
* Watcher instance
Expand Down Expand Up @@ -77,25 +77,47 @@ export class Server
public async boot(): Promise<void> {
this.application = Express()

this.app.hooks.on('server.middleware', () => middleware)
this.app.hooks
.on('server.middleware', () => middleware)

.hooks.on('server.inject', () => [
instance =>
`@roots/bud-server/client/index.js?name=${instance.name}&path=/__bud/hmr`,
])

.hooks.async('event.server.before', async app => {
app.when(
({store}) => store.is('features.proxy', true),
({hooks}) =>
hooks.on('server.inject', inject => [
...inject,
() => `@roots/bud-server/client/proxy-click-interceptor.js`,
]),
)

return app
})
}

this.app.hooks.on('server.inject', () => [
instance =>
`@roots/bud-server/client/index.js?name=${instance.name}&path=/__bud/hmr`,
])
/**
* Apply middlewares
*
* @returns
*/
public applyMiddlewares() {
Object.entries(this.app.hooks.filter('server.middleware')).map(
([key, factory]) => {
this.log(`info`, `using middleware: ${key}`)

this.app.hooks.async('event.server.before', async app => {
app.when(
({store}) => store.is('features.proxy', true),
({hooks}) =>
hooks.on('server.inject', inject => [
...inject,
() => `@roots/bud-server/client/proxy-click-interceptor.js`,
]),
)
const middleware = factory(this.app)

return app
})
Object.assign(this.middleware, {
[key]: middleware,
})

this.application.use(this.middleware[key])
},
)
}

/**
Expand Down Expand Up @@ -124,16 +146,7 @@ export class Server
*/
await this.compile()

/**
* Apply middleware
*/
Object.entries(this.app.hooks.filter('server.middleware')).map(
([key, factory]) => {
this.log(`info`, `using middleware: ${key}`)
const middleware = factory(this.app)
middleware && this.application.use(middleware)
},
)
this.applyMiddlewares()

/**
* 404 middleware
Expand Down
4 changes: 2 additions & 2 deletions sources/@roots/bud-server/src/server/server.watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class Watcher {
*/
@bind
public async getWatchedFiles(): Promise<Array<string>> {
const [files, options] = this.app.store.getValues('server.watch')
const {files, options} = this.app.store.get('server.watch')

if (!files?.length) return []

Expand Down Expand Up @@ -53,7 +53,7 @@ export class Watcher {
if (watchFiles.length) {
this.instance = chokidar.watch(
watchFiles.map(entry => {
this.app.log('log', `watching`, entry, `for changes`)
this.app.log(`watching`, entry, `for changes`)
return entry
}),
)
Expand Down
1 change: 1 addition & 0 deletions sources/@roots/bud/src/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ export const seed: Partial<Store.Repository> = {
server: {
watch: {
files: [],
options: {},
},

middleware: {
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/bud-api/repository/__snapshots__/watch.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`bud.watch merges watch files 1`] = `
Array [
"**/*.js",
"foo/*.js",
]
`;

exports[`bud.watch merges watch options 1`] = `
Object {
"cwd": "/srv/www",
"depth": 1,
}
`;

exports[`bud.watch set watch options 1`] = `
Object {
"depth": 1,
}
`;

exports[`bud.watch sets watch files 1`] = `
Array [
"**/*.js",
Expand Down
46 changes: 35 additions & 11 deletions tests/unit/bud-api/repository/watch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,52 @@ describe('bud.watch', function () {
let bud: Bud

beforeAll(async () => {
bud = await factory({
mode: 'development',
})
bud = await factory()
})

it('is a function', () => {
expect(bud.watch).toBeInstanceOf(Function)
})

it("doesn't throw when called in production", () => {
expect(bud.watch(['**/*.js'])).toBeInstanceOf(Bud)
it('sets watch files', async () => {
bud.watch(['**/*.js'])

await bud.api.processQueue()

expect(bud.store.get('server.watch.files')).toMatchSnapshot([
'**/*.js',
])
})

it('sets watch files', async () => {
const files = ['**/*.js']
it('merges watch files', async () => {
bud.watch(['foo/*.js'])

await bud.api.processQueue()

bud.watch(files)
expect(bud.store.get('server.watch.files')).toMatchSnapshot([
'**/*.js',
'foo/*.js',
])
})

it('set watch options', async () => {
bud.watch([], {depth: 1})

await bud.api.processQueue()

expect(bud.store.get('server.watch.options')).toMatchSnapshot({
depth: 1,
})
})

it('merges watch options', async () => {
bud.watch([], {cwd: '/srv/www'})

await bud.api.processQueue()

expect(bud.store.get('server.watch.files')).toMatchSnapshot(
files,
)
expect(bud.store.get('server.watch.options')).toMatchSnapshot({
cwd: '/srv/www',
depth: 1,
})
})
})
1 change: 1 addition & 0 deletions tests/unit/bud-server/__snapshots__/service.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Object {
},
"watch": Object {
"files": Array [],
"options": Object {},
},
}
`;
20 changes: 20 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4186,6 +4186,7 @@ __metadata:
"@types/js-yaml": 4.0.5
"@types/lodash": 4.14.178
"@types/node": 16.11.19
chokidar: ^3.5.3
cli-highlight: ^2.1.11
http-proxy-middleware: 2.0.1
ink: 3.2.0
Expand Down Expand Up @@ -9245,6 +9246,25 @@ __metadata:
languageName: node
linkType: hard

"chokidar@npm:^3.5.3":
version: 3.5.3
resolution: "chokidar@npm:3.5.3"
dependencies:
anymatch: ~3.1.2
braces: ~3.0.2
fsevents: ~2.3.2
glob-parent: ~5.1.2
is-binary-path: ~2.1.0
is-glob: ~4.0.1
normalize-path: ~3.0.0
readdirp: ~3.6.0
dependenciesMeta:
fsevents:
optional: true
checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c
languageName: node
linkType: hard

"chownr@npm:^2.0.0":
version: 2.0.0
resolution: "chownr@npm:2.0.0"
Expand Down

0 comments on commit 582c3f3

Please sign in to comment.