Skip to content

Commit 6298cc9

Browse files
committed
feat: allow inline hooks
1 parent 2cfe1a2 commit 6298cc9

File tree

3 files changed

+117
-18
lines changed

3 files changed

+117
-18
lines changed

src/types/hooks.ts

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
import { type Instructions } from '@poppinss/cliui'
11-
import { type UnWrapLazyImport, type AsyncOrSync, type LazyImport } from '@poppinss/utils/types'
11+
import { type AsyncOrSync, type LazyImport } from '@poppinss/utils/types'
1212

1313
import { type Bundler } from '../bundler.ts'
1414
import { type DevServer } from '../dev_server.ts'
@@ -17,6 +17,24 @@ import { type RoutesListItem } from './code_scanners.ts'
1717
import { type IndexGenerator } from '../index_generator/main.ts'
1818
import { type RoutesScanner } from '../code_scanners/routes_scanner/main.ts'
1919

20+
/**
21+
* Defines a hook that can be either a lazy import or an object with a run method.
22+
* This type provides flexibility in how hooks are defined and imported, supporting
23+
* both dynamic imports for code splitting and direct object definitions.
24+
*
25+
* @template Fn - The function signature that the hook must conform to
26+
*
27+
* @example
28+
* // Using lazy import
29+
* const hook: DefineHook<(server: DevServer) => void> = () => import('./my-hook')
30+
*
31+
* // Using direct object
32+
* const hook: DefineHook<(server: DevServer) => void> = {
33+
* run: (server) => console.log('Hook executed')
34+
* }
35+
*/
36+
type DefineHook<Fn extends (...args: any) => any> = LazyImport<Fn> | { run: Fn }
37+
2038
/**
2139
* Common hooks executed by the dev-server, test runner and the bundler.
2240
* These hooks are shared across all assembler operations and provide
@@ -37,7 +55,7 @@ export type CommonHooks = {
3755
*
3856
* @param parent - The parent instance (DevServer, TestRunner, or Bundler)
3957
*/
40-
init: LazyImport<
58+
init: DefineHook<
4159
(parent: DevServer | TestRunner | Bundler, indexGenerator: IndexGenerator) => AsyncOrSync<void>
4260
>[]
4361
}
@@ -67,7 +85,7 @@ export type RouterHooks = {
6785
* @param parent - The DevServer instance
6886
* @param routes - Record of routes grouped by domain or method
6987
*/
70-
routesCommitted: LazyImport<
88+
routesCommitted: DefineHook<
7189
(parent: DevServer, routes: Record<string, RoutesListItem[]>) => AsyncOrSync<void>
7290
>[]
7391

@@ -78,7 +96,7 @@ export type RouterHooks = {
7896
* @param parent - The DevServer instance
7997
* @param routesScanner - The RoutesScanner instance being used
8098
*/
81-
routesScanning: LazyImport<
99+
routesScanning: DefineHook<
82100
(parent: DevServer, routesScanner: RoutesScanner) => AsyncOrSync<void>
83101
>[]
84102

@@ -89,7 +107,7 @@ export type RouterHooks = {
89107
* @param parent - The DevServer instance
90108
* @param routesScanner - The RoutesScanner instance that was used
91109
*/
92-
routesScanned: LazyImport<
110+
routesScanned: DefineHook<
93111
(parent: DevServer, routesScanner: RoutesScanner) => AsyncOrSync<void>
94112
>[]
95113
}
@@ -126,7 +144,7 @@ export type WatcherHooks = {
126144
* @param info.fullReload - Whether a full server reload is required
127145
* @param parent - The parent DevServer or TestRunner instance
128146
*/
129-
fileChanged: LazyImport<
147+
fileChanged: DefineHook<
130148
(
131149
relativePath: string,
132150
absolutePath: string,
@@ -149,7 +167,7 @@ export type WatcherHooks = {
149167
* @param filePath - The absolute path to the added file
150168
* @param server - The DevServer or TestRunner instance
151169
*/
152-
fileAdded: LazyImport<
170+
fileAdded: DefineHook<
153171
(
154172
relativePath: string,
155173
absolutePath: string,
@@ -164,7 +182,7 @@ export type WatcherHooks = {
164182
* @param filePath - The absolute path to the removed file
165183
* @param server - The DevServer or TestRunner instance
166184
*/
167-
fileRemoved: LazyImport<
185+
fileRemoved: DefineHook<
168186
(
169187
relativePath: string,
170188
absolutePath: string,
@@ -193,7 +211,7 @@ export type DevServerHooks = {
193211
*
194212
* @param server - The DevServer instance that is about to start
195213
*/
196-
devServerStarting: LazyImport<(server: DevServer) => AsyncOrSync<void>>[]
214+
devServerStarting: DefineHook<(server: DevServer) => AsyncOrSync<void>>[]
197215

198216
/**
199217
* The hook is executed after the child process has been started.
@@ -205,7 +223,7 @@ export type DevServerHooks = {
205223
* @param info.host - The host address the server is bound to
206224
* @param uiInstructions - UI instructions for displaying server information
207225
*/
208-
devServerStarted: LazyImport<
226+
devServerStarted: DefineHook<
209227
(
210228
server: DevServer,
211229
info: { port: number; host: string },
@@ -234,7 +252,7 @@ export type BundlerHooks = {
234252
*
235253
* @param server - The Bundler instance that will create the build
236254
*/
237-
buildStarting: LazyImport<(server: Bundler) => AsyncOrSync<void>>[]
255+
buildStarting: DefineHook<(server: Bundler) => AsyncOrSync<void>>[]
238256

239257
/**
240258
* The hook is executed after the production build has been created.
@@ -243,7 +261,7 @@ export type BundlerHooks = {
243261
* @param server - The Bundler instance that created the build
244262
* @param uiInstructions - UI instructions for displaying build information
245263
*/
246-
buildFinished: LazyImport<(server: Bundler, uiInstructions: Instructions) => AsyncOrSync<void>>[]
264+
buildFinished: DefineHook<(server: Bundler, uiInstructions: Instructions) => AsyncOrSync<void>>[]
247265
}
248266

249267
/**
@@ -266,15 +284,15 @@ export type TestRunnerHooks = {
266284
*
267285
* @param server - The TestRunner instance that will execute the tests
268286
*/
269-
testsStarting: LazyImport<(server: TestRunner) => AsyncOrSync<void>>[]
287+
testsStarting: DefineHook<(server: TestRunner) => AsyncOrSync<void>>[]
270288

271289
/**
272290
* The hook is executed after the tests have been executed.
273291
* Use this hook to clean up resources or generate test reports.
274292
*
275293
* @param server - The TestRunner instance that executed the tests
276294
*/
277-
testsFinished: LazyImport<(server: TestRunner) => AsyncOrSync<void>>[]
295+
testsFinished: DefineHook<(server: TestRunner) => AsyncOrSync<void>>[]
278296
}
279297

280298
/**
@@ -319,6 +337,5 @@ export type AllHooks = CommonHooks &
319337
* // Result: [DevServer, {port: number, host: string}, Instructions]
320338
* ```
321339
*/
322-
export type HookParams<Hook extends keyof AllHooks> = Parameters<
323-
UnWrapLazyImport<AllHooks[Hook][number]>
324-
>
340+
export type HookParams<Hook extends keyof AllHooks> =
341+
AllHooks[Hook][number] extends DefineHook<infer A> ? Parameters<A> : never

src/utils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,11 @@ export async function loadHooks<K extends keyof AllHooks>(
336336

337337
for (const { group, hooks: collection } of groups) {
338338
for (const item of collection) {
339-
hooks.add(group, await importDefault<{}>(item))
339+
if ('run' in item) {
340+
hooks.add(group, item.run as any)
341+
} else {
342+
hooks.add(group, await importDefault<{}>(item))
343+
}
340344
}
341345
}
342346

tests/dev_server.spec.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,84 @@ test.group('DevServer', () => {
9797
assert.deepEqual(hooksStack, ['init', 'devServerStarting', 'devServerStarted'])
9898
})
9999

100+
test('define hooks as inline functions', async ({ fs, assert, cleanup }) => {
101+
let hooksStack: string[] = []
102+
103+
await fs.createJson('tsconfig.json', {
104+
extends: '@adonisjs/tsconfig/tsconfig.package.json',
105+
compilerOptions: {
106+
rootDir: './',
107+
outDir: './build',
108+
},
109+
})
110+
await fs.create(
111+
'bin/server.ts',
112+
`process.send({ isAdonisJS: true, environment: 'web', port: process.env.PORT, host: 'localhost' })`
113+
)
114+
await fs.create('.env', 'PORT=3334')
115+
116+
const devServer = new DevServer(fs.baseUrl, {
117+
nodeArgs: [],
118+
scriptArgs: [],
119+
metaFiles: [],
120+
suites: [],
121+
hooks: {
122+
init: [
123+
{
124+
run() {
125+
hooksStack.push('init')
126+
},
127+
},
128+
],
129+
devServerStarted: [
130+
{
131+
run() {
132+
hooksStack.push('devServerStarted')
133+
},
134+
},
135+
],
136+
devServerStarting: [
137+
{
138+
run() {
139+
hooksStack.push('devServerStarting')
140+
},
141+
},
142+
],
143+
},
144+
})
145+
146+
devServer.ui = cliui()
147+
devServer.ui.switchMode('raw')
148+
149+
await devServer.start(ts)
150+
cleanup(async () => devServer.close())
151+
152+
assert.deepEqual(devServer.ui.logger.getLogs(), [
153+
{
154+
message: '[ blue(info) ] starting server in static mode...',
155+
stream: 'stdout',
156+
},
157+
{
158+
message: '[ blue(info) ] loading hooks...',
159+
stream: 'stdout',
160+
},
161+
{
162+
message: '[ blue(info) ] generating indexes...',
163+
stream: 'stdout',
164+
},
165+
{
166+
message: '[ blue(info) ] starting HTTP server...',
167+
stream: 'stdout',
168+
},
169+
{
170+
message:
171+
'Server address: cyan(http://localhost:3334)\nMode: cyan(static)\nPress dim(h) to show help',
172+
stream: 'stdout',
173+
},
174+
])
175+
assert.deepEqual(hooksStack, ['init', 'devServerStarting', 'devServerStarted'])
176+
})
177+
100178
test('start in watch mode and execute hook', async ({ fs, assert, cleanup }) => {
101179
let hooksStack: string[] = []
102180

0 commit comments

Comments
 (0)