Skip to content

Commit f0c2896

Browse files
committed
feat: add TestRunner service
1 parent c2fec3d commit f0c2896

File tree

12 files changed

+803
-370
lines changed

12 files changed

+803
-370
lines changed

index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99

1010
export { Bundler } from './src/bundler.js'
1111
export { DevServer } from './src/dev_server.js'
12+
export { TestRunner } from './src/test_runner.js'

src/assets_dev_server.ts

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* @adonisjs/core
3+
*
4+
* (c) AdonisJS
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
import type { ExecaChildProcess } from 'execa'
11+
import { type Logger, cliui } from '@poppinss/cliui'
12+
13+
import { run } from './helpers.js'
14+
import type { AssetsBundlerOptions } from './types.js'
15+
16+
/**
17+
* Instance of CLIUI
18+
*/
19+
const ui = cliui()
20+
21+
/**
22+
* Exposes the API to start the development server for processing assets during
23+
* development.
24+
*
25+
* - Here we are running the assets dev server in a child process.
26+
* - Piping the output from the child process and reformatting it before writing it to
27+
* process streams.
28+
*
29+
* AssetsDevServer is agnostic and can run any assets dev server. Be it Vite or Encore or
30+
* even Webpack directly.
31+
*/
32+
export class AssetsDevServer {
33+
#cwd: URL
34+
#logger = ui.logger
35+
#options?: AssetsBundlerOptions
36+
#devServer?: ExecaChildProcess<string>
37+
38+
/**
39+
* Getting reference to colors library from logger
40+
*/
41+
get #colors() {
42+
return this.#logger.getColors()
43+
}
44+
45+
constructor(cwd: URL, options?: AssetsBundlerOptions) {
46+
this.#cwd = cwd
47+
this.#options = options
48+
}
49+
50+
/**
51+
* Logs messages from vite dev server stdout and stderr
52+
*/
53+
#logViteDevServerMessage(data: Buffer) {
54+
const dataString = data.toString()
55+
const lines = dataString.split('\n')
56+
57+
/**
58+
* Logging VITE ready in message with proper
59+
* spaces and newlines
60+
*/
61+
if (dataString.includes('ready in')) {
62+
console.log('')
63+
console.log(dataString.trim())
64+
return
65+
}
66+
67+
/**
68+
* Put a wrapper around vite network address log
69+
*/
70+
if (dataString.includes('Local') && dataString.includes('Network')) {
71+
const sticker = ui.sticker().useColors(this.#colors).useRenderer(this.#logger.getRenderer())
72+
73+
lines.forEach((line: string) => {
74+
if (line.trim()) {
75+
sticker.add(line)
76+
}
77+
})
78+
79+
sticker.render()
80+
return
81+
}
82+
83+
/**
84+
* Log rest of the lines
85+
*/
86+
lines.forEach((line: string) => {
87+
if (line.trim()) {
88+
console.log(line)
89+
}
90+
})
91+
}
92+
93+
/**
94+
* Logs messages from assets dev server stdout and stderr
95+
*/
96+
#logAssetsDevServerMessage(data: Buffer) {
97+
const dataString = data.toString()
98+
const lines = dataString.split('\n')
99+
lines.forEach((line: string) => {
100+
if (line.trim()) {
101+
console.log(line)
102+
}
103+
})
104+
}
105+
106+
/**
107+
* Set a custom CLI UI logger
108+
*/
109+
setLogger(logger: Logger) {
110+
this.#logger = logger
111+
return this
112+
}
113+
114+
/**
115+
* Starts the assets bundler server. The assets bundler server process is
116+
* considered as the secondary process and therefore we do not perform
117+
* any cleanup if it dies.
118+
*/
119+
start() {
120+
if (!this.#options?.serve) {
121+
return
122+
}
123+
124+
this.#logger.info(`starting "${this.#options.driver}" dev server...`)
125+
126+
/**
127+
* Create child process
128+
*/
129+
this.#devServer = run(this.#cwd, {
130+
script: this.#options.cmd,
131+
132+
/**
133+
* We do not inherit the stdio for vite and encore, because in
134+
* inherit mode they own the stdin and interrupts the
135+
* `Ctrl + C` command.
136+
*/
137+
stdio: 'pipe',
138+
scriptArgs: this.#options.args,
139+
})
140+
141+
/**
142+
* Log child process messages
143+
*/
144+
this.#devServer.stdout?.on('data', (data) => {
145+
if (this.#options!.driver === 'vite') {
146+
this.#logViteDevServerMessage(data)
147+
} else {
148+
this.#logAssetsDevServerMessage(data)
149+
}
150+
})
151+
152+
this.#devServer.stderr?.on('data', (data) => {
153+
if (this.#options!.driver === 'vite') {
154+
this.#logViteDevServerMessage(data)
155+
} else {
156+
this.#logAssetsDevServerMessage(data)
157+
}
158+
})
159+
160+
this.#devServer
161+
.then((result) => {
162+
this.#logger.warning(
163+
`"${this.#options!.driver}" dev server closed with status code "${result.exitCode}"`
164+
)
165+
})
166+
.catch((error) => {
167+
this.#logger.warning(`unable to connect to "${this.#options!.driver}" dev server`)
168+
this.#logger.fatal(error)
169+
})
170+
}
171+
172+
/**
173+
* Stop the dev server
174+
*/
175+
stop() {
176+
if (this.#devServer) {
177+
this.#devServer.removeAllListeners()
178+
this.#devServer.kill('SIGKILL')
179+
this.#devServer = undefined
180+
}
181+
}
182+
}

src/bundler.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import { fileURLToPath } from 'node:url'
1515
import { join, relative } from 'node:path'
1616
import { cliui, type Logger } from '@poppinss/cliui'
1717

18-
import { run } from './run.js'
19-
import { parseConfig } from './parse_config.js'
18+
import { run, parseConfig } from './helpers.js'
2019
import type { BundlerOptions } from './types.js'
2120

2221
/**

0 commit comments

Comments
 (0)