({ watch = false } = {})
| 163 | } |
| 164 | |
| 165 | async function build({ watch = false } = {}) { |
| 166 | await fs.mkdir(DIST_DIR, { recursive: true }); |
| 167 | MODULE_DIR = TS_OUT_DIR; |
| 168 | |
| 169 | await compileProto(); |
| 170 | await compileTypeScript(); |
| 171 | |
| 172 | const entryId = canonicalId(path.resolve(MODULE_DIR, ENTRY)); |
| 173 | const modules = await collectModules(entryId); |
| 174 | const bundle = createBundle(modules, entryId); |
| 175 | |
| 176 | const indexPath = path.join(SOURCE_DIR, 'index.html'); |
| 177 | let html = await fs.readFile(indexPath, 'utf-8'); |
| 178 | html = await inlineStyles(html, SOURCE_DIR); |
| 179 | |
| 180 | const vuePlaceholder = /<script\s+src=["']\.\.\/vendor\/vue\.global\.prod\.js["']><\/script>/i; |
| 181 | const vuePath = path.join(ROOT, 'vendor/vue.global.prod.js'); |
| 182 | let vueInlined = false; |
| 183 | try { |
| 184 | const vueCode = await fs.readFile(vuePath, 'utf-8'); |
| 185 | html = html.replace(vuePlaceholder, `<script>\n${vueCode}\n</script>`); |
| 186 | vueInlined = true; |
| 187 | } catch { |
| 188 | console.warn('Warning: vendor/vue.global.prod.js not found – using CDN fallback.'); |
| 189 | } |
| 190 | if (!vueInlined) { |
| 191 | html = html.replace( |
| 192 | vuePlaceholder, |
| 193 | '<script src="https://unpkg.com/vue@3.4.21/dist/vue.global.prod.js"></script>', |
| 194 | ); |
| 195 | } |
| 196 | |
| 197 | html = await inlineScripts(html, [ |
| 198 | { |
| 199 | placeholder: '<script src="./main.js"></script>', |
| 200 | code: bundle, |
| 201 | }, |
| 202 | ]); |
| 203 | |
| 204 | const distFile = path.join(DIST_DIR, 'index.html'); |
| 205 | await fs.writeFile(distFile, html); |
| 206 | |
| 207 | const targetFile = process.env.DSTACK_UI_OUT |
| 208 | ? path.resolve(process.env.DSTACK_UI_OUT) |
| 209 | : path.resolve(ROOT, '../src/console_v1.html'); |
| 210 | await fs.mkdir(path.dirname(targetFile), { recursive: true }); |
| 211 | await fs.writeFile(targetFile, html); |
| 212 | |
| 213 | if (watch) { |
| 214 | console.log('Watching for changes...'); |
| 215 | const watcher = fs.watch(SOURCE_DIR, { recursive: true }, async () => { |
| 216 | try { |
| 217 | await compileProto(); |
| 218 | await compileTypeScript(); |
| 219 | const mods = await collectModules(entryId); |
| 220 | const rebundle = createBundle(mods, entryId); |
| 221 | let rehtml = await fs.readFile(indexPath, 'utf-8'); |
| 222 | rehtml = await inlineStyles(rehtml, SOURCE_DIR); |
no test coverage detected