1 | #!/usr/bin/env node
|
2 |
|
3 | const
|
4 | parseArgs = require('minimist'),
|
5 | chalk = require('chalk')
|
6 |
|
7 | const
|
8 | logger = require('../lib/helpers/logger'),
|
9 | log = logger('app:dev'),
|
10 | warn = logger('app:dev', 'red'),
|
11 | appPaths = require('../lib/app-paths')
|
12 |
|
13 | const argv = parseArgs(process.argv.slice(2), {
|
14 | alias: {
|
15 | t: 'theme',
|
16 | m: 'mode',
|
17 | T: 'target', // cordova-mode only
|
18 | e: 'emulator', // cordova-mode only
|
19 | p: 'port',
|
20 | H: 'hostname',
|
21 | h: 'help'
|
22 | },
|
23 | boolean: ['h'],
|
24 | string: ['t', 'm', 'T', 'H'],
|
25 | default: {
|
26 | t: 'mat',
|
27 | m: 'spa'
|
28 | }
|
29 | })
|
30 |
|
31 | if (argv.help) {
|
32 | console.log(`
|
33 | Description
|
34 | Starts the app in development mode (hot-code reloading, error
|
35 | reporting, etc)
|
36 | Usage
|
37 | $ quasar dev -p <port number>
|
38 | Options
|
39 | --theme, -t App theme (default: mat)
|
40 | --mode, -m App mode [spa|ssr|pwa|cordova|electron] (default: spa)
|
41 | --port, -p A port number on which to start the application
|
42 | --hostname, -H A hostname to use for serving the application
|
43 | --help, -h Displays this message
|
44 |
|
45 | Only for Cordova mode:
|
46 | --target, -T (required) App target
|
47 | [android|ios|blackberry10|browser|osx|ubuntu|webos|windows]
|
48 | --emulator, -e (optional) Emulator name
|
49 | Example: iPhone-7, iPhone-X
|
50 | `)
|
51 | process.exit(0)
|
52 | }
|
53 |
|
54 | require('../lib/helpers/ensure-argv')(argv, 'dev')
|
55 | require('../lib/helpers/banner')(argv, 'dev')
|
56 |
|
57 | if (argv.mode !== 'spa') {
|
58 | require('../lib/mode/install-missing')(argv.mode, argv.target)
|
59 | }
|
60 |
|
61 | const
|
62 | ensureDeps = require('../lib/helpers/ensure-deps'),
|
63 | findPort = require('../lib/helpers/net').findClosestOpenPort
|
64 |
|
65 | async function parseAddress ({ host, port }) {
|
66 | if (this.chosenHost) {
|
67 | host = this.chosenHost
|
68 | }
|
69 | else {
|
70 | if (host && ['localhost', '127.0.0.1', '::1'].includes(host.toLowerCase())) {
|
71 | host = '0.0.0.0'
|
72 | }
|
73 | if (argv.mode === 'cordova' && (!host || host === '0.0.0.0')) {
|
74 | const getExternalIP = require('../lib/helpers/get-external-ip')
|
75 | host = await getExternalIP()
|
76 | this.chosenHost = host
|
77 | }
|
78 | }
|
79 |
|
80 | log(`Checking listening address availability (${host}:${port})...`)
|
81 |
|
82 | try {
|
83 | const openPort = await findPort(port, host)
|
84 | if (port !== openPort) {
|
85 | warn()
|
86 | warn(`Setting port to closest one available: ${openPort}`)
|
87 | warn()
|
88 |
|
89 | port = openPort
|
90 | }
|
91 | }
|
92 | catch (e) {
|
93 | warn()
|
94 |
|
95 | if (e.message === 'ERROR_NETWORK_PORT_NOT_AVAIL') {
|
96 | warn(`⚠️ Could not find an open port. Please configure a lower one to start searching with.`)
|
97 | }
|
98 | else if (e.message === 'ERROR_NETWORK_ADDRESS_NOT_AVAIL') {
|
99 | warn(`⚠️ Invalid host specified. No network address matches. Please specify another one.`)
|
100 | }
|
101 | else {
|
102 | warn(`⚠️ Unknown network error occured`)
|
103 | console.log(e)
|
104 | }
|
105 |
|
106 | warn()
|
107 |
|
108 | if (!this.running) {
|
109 | process.exit(1)
|
110 | }
|
111 |
|
112 | return null
|
113 | }
|
114 |
|
115 | this.running = true
|
116 | return { host, port }
|
117 | }
|
118 |
|
119 | async function goLive () {
|
120 | ensureDeps()
|
121 |
|
122 | const
|
123 | DevServer = require('../lib/dev-server'),
|
124 | QuasarConfig = require('../lib/quasar-config'),
|
125 | Generator = require('../lib/generator')
|
126 |
|
127 | const
|
128 | quasarConfig = new QuasarConfig({
|
129 | theme: argv.theme,
|
130 | mode: argv.mode,
|
131 | target: argv.target,
|
132 | emulator: argv.emulator,
|
133 | port: argv.port,
|
134 | host: argv.hostname,
|
135 | dev: true,
|
136 | onAddress: parseAddress,
|
137 | onBuildChange () {
|
138 | log(`Build changes detected. Rebuilding app...`)
|
139 | dev = dev.then(startDev)
|
140 | },
|
141 | onAppChange () {
|
142 | log(`App changes detected. Updating app...`)
|
143 | generator.build()
|
144 | }
|
145 | })
|
146 |
|
147 | try {
|
148 | await quasarConfig.prepare()
|
149 | }
|
150 | catch (e) {
|
151 | console.log(e)
|
152 | warn(`[FAIL] quasar.conf.js has JS errors`)
|
153 | process.exit(1)
|
154 | }
|
155 |
|
156 | quasarConfig.compile()
|
157 |
|
158 | const
|
159 | generator = new Generator(quasarConfig),
|
160 | Cordova = argv.mode === 'cordova' ? require('../lib/cordova') : false,
|
161 | Electron = argv.mode === 'electron' ? require('../lib/electron') : false
|
162 |
|
163 | generator.prepare()
|
164 |
|
165 | function startDev (oldDevServer) {
|
166 | let devServer
|
167 |
|
168 | return Promise.resolve()
|
169 | .then(() => devServer = new DevServer(quasarConfig))
|
170 | .then(() => oldDevServer && oldDevServer.stop())
|
171 | .then(() => generator.build()) // Update generated files
|
172 | .then(() => devServer.listen()) // Start listening
|
173 | .then(() => Electron && Electron.run(quasarConfig))
|
174 | .then(() => Cordova && Cordova.run(quasarConfig))
|
175 | .then(() => devServer) // Pass new builder to watch chain
|
176 | }
|
177 |
|
178 | let dev = startDev()
|
179 | }
|
180 |
|
181 | goLive()
|