-
-
Notifications
You must be signed in to change notification settings - Fork 621
/
serve.ts
181 lines (160 loc) · 5.14 KB
/
serve.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
* @adonisjs/core
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import type { DevServer } from '@adonisjs/assembler'
import type { CommandOptions } from '../types/ace.js'
import { BaseCommand, flags } from '../modules/ace/main.js'
import { detectAssetsBundler, importAssembler, importTypeScript } from '../src/internal_helpers.js'
/**
* Serve command is used to run the AdonisJS HTTP server during development. The
* command under the hood runs the "bin/server.ts" file and watches for file
* system changes
*/
export default class Serve extends BaseCommand {
static commandName = 'serve'
static description =
'Start the development HTTP server along with the file watcher to perform restarts on file change'
static help = [
'Start the development server with file watcher using the following command.',
'```',
'{{ binaryName }} serve --watch',
'```',
'',
'You can also start the server with HMR support using the following command.',
'```',
'{{ binaryName }} serve --hmr',
'```',
'',
'The assets bundler dev server runs automatically after detecting vite config or webpack config files',
'You may pass vite CLI args using the --assets-args command line flag.',
'```',
'{{ binaryName }} serve --assets-args="--debug --base=/public"',
'```',
]
static options: CommandOptions = {
staysAlive: true,
}
declare devServer: DevServer
@flags.boolean({ description: 'Start the server with HMR support' })
declare hmr?: boolean
@flags.boolean({
description: 'Watch filesystem and restart the HTTP server on file change',
alias: 'w',
})
declare watch?: boolean
@flags.boolean({ description: 'Use polling to detect filesystem changes', alias: 'p' })
declare poll?: boolean
@flags.boolean({
description: 'Clear the terminal for new logs after file change',
showNegatedVariantInHelp: true,
default: true,
})
declare clear?: boolean
@flags.boolean({
description: 'Start assets bundler dev server',
showNegatedVariantInHelp: true,
default: true,
})
declare assets?: boolean
@flags.array({
description: 'Define CLI arguments to pass to the assets bundler',
})
declare assetsArgs?: string[]
/**
* Log a development dependency is missing
*/
#logMissingDevelopmentDependency(dependency: string) {
this.logger.error(
[
`Cannot find package "${dependency}"`,
'',
`The "${dependency}" package is a development dependency and therefore you should use the serve command during development only.`,
'',
'If you are running your application in production, then use "node bin/server.js" command to start the HTTP server',
].join('\n')
)
}
/**
* Returns the assets bundler config
*/
async #getAssetsBundlerConfig() {
const assetsBundler = await detectAssetsBundler(this.app)
return assetsBundler
? {
enabled: this.assets === false ? false : true,
driver: assetsBundler.name,
cmd: assetsBundler.devServer.command,
args: (assetsBundler.devServer.args || []).concat(this.assetsArgs || []),
}
: {
enabled: false as const,
}
}
/**
* Runs the HTTP server
*/
async run() {
const assembler = await importAssembler(this.app)
if (!assembler) {
this.#logMissingDevelopmentDependency('@adonisjs/assembler')
this.exitCode = 1
return
}
if (this.watch && this.hmr) {
this.logger.error('Cannot use --watch and --hmr flags together. Choose one of them')
this.exitCode = 1
return
}
this.devServer = new assembler.DevServer(this.app.appRoot, {
hmr: this.hmr === true ? true : false,
clearScreen: this.clear === false ? false : true,
nodeArgs: this.parsed.nodeArgs,
scriptArgs: [],
assets: await this.#getAssetsBundlerConfig(),
metaFiles: this.app.rcFile.metaFiles,
hooks: {
onDevServerStarted: this.app.rcFile.unstable_assembler?.onDevServerStarted,
onSourceFileChanged: this.app.rcFile.unstable_assembler?.onSourceFileChanged,
onHttpServerMessage: this.app.rcFile.unstable_assembler?.onHttpServerMessage,
},
})
/**
* Share command logger with assembler, so that CLI flags like --no-ansi has
* similar impact for assembler logs as well.
*/
this.devServer.setLogger(this.logger)
/**
* Exit command when the dev server is closed
*/
this.devServer.onClose((exitCode) => {
this.exitCode = exitCode
this.terminate()
})
/**
* Exit command when the dev server crashes
*/
this.devServer.onError(() => {
this.exitCode = 1
this.terminate()
})
/**
* Start the development server
*/
if (this.watch) {
const ts = await importTypeScript(this.app)
if (!ts) {
this.#logMissingDevelopmentDependency('typescript')
this.exitCode = 1
return
}
await this.devServer.startAndWatch(ts, { poll: this.poll || false })
} else {
await this.devServer.start()
}
}
}