11import type { Listener } from 'listhen'
22import type { Buffer } from 'node:buffer'
33import type { IncomingMessage } from 'node:http'
4+ import type { InputOptions , OutputOptions , RollupBuild } from 'rollup'
45import type { WebSocket } from 'ws'
56import type { NuxtDiscordContext , SlashCommand } from '../types'
6- import { existsSync , globSync , readFileSync , writeFileSync } from 'node:fs'
7+ import { existsSync , globSync , mkdirSync , readFileSync , writeFileSync } from 'node:fs'
8+ import path from 'node:path'
79import { addVitePlugin , isIgnored , updateTemplates } from '@nuxt/kit'
10+ import chokidar from 'chokidar'
811import { listen } from 'listhen'
12+ import { rollup } from 'rollup'
913import { WebSocketServer } from 'ws'
1014import collectSlashCommands , { processCommandFile } from './collect'
1115
16+ type RollupConfig = InputOptions & {
17+ output : OutputOptions
18+ }
19+
1220export function prepareHMR ( ctx : NuxtDiscordContext ) {
1321 const { nuxt, options } = ctx
1422
@@ -23,6 +31,8 @@ export function prepareHMR(ctx: NuxtDiscordContext) {
2331 }
2432
2533 // nitro dev server ignore discord commands directory
34+ let rollupConfig : RollupConfig
35+
2636 nuxt . hook ( 'nitro:config' , ( nitroConfig ) => {
2737 nitroConfig . watchOptions ??= { }
2838 const existingNitroIgnored = nitroConfig . watchOptions . ignored
@@ -34,7 +44,13 @@ export function prepareHMR(ctx: NuxtDiscordContext) {
3444 nitroIgnored . push ( existingNitroIgnored )
3545 }
3646 // TODO: stop ignoring the commands directory, come back if I figure out how to make HMR work on server
37- // nitroConfig.watchOptions.ignored = nitroIgnored
47+ nitroConfig . watchOptions . ignored = nitroIgnored
48+
49+ nitroConfig . hooks ??= {
50+ 'rollup:before' : ( _ , config ) => {
51+ rollupConfig = config
52+ } ,
53+ }
3854 } )
3955
4056 // vite dev server ignore discord commands directory
@@ -84,19 +100,23 @@ export function prepareHMR(ctx: NuxtDiscordContext) {
84100 } )
85101 }
86102
87- nuxt . hook ( 'builder:watch' , async ( event , path ) => {
88- const fullPath = ctx . resolve . root ( path )
89- if ( fullPath . startsWith ( commandsDir ) ) {
90- path = ctx . resolve . root ( path )
91- const command = processCommandFile ( ctx , path ) ?? null
92- websocket ?. broadcast ( { event, path, command } )
103+ chokidar . watch ( ctx . resolve . root ( ctx . options . dir , 'commands' ) , { ignoreInitial : true } )
104+ . on ( 'all' , async ( event , path ) => {
105+ const fullPath = ctx . resolve . root ( path )
106+ if ( fullPath . startsWith ( commandsDir ) ) {
107+ path = ctx . resolve . root ( path )
108+ const command = processCommandFile ( ctx , path ) ?? null
109+ websocket ?. broadcast ( { event, path, command } )
110+ if ( event === 'add' || event === 'change' ) {
111+ await generateDynamicCommandBuild ( path , rollupConfig , ctx )
112+ }
93113
94- // I don't think this is doing anything at all...
95- await updateTemplates ( {
96- filter : template => template . filename === 'discord/slashCommands' ,
97- } )
98- }
99- } )
114+ // I don't think this is doing anything at all...
115+ await updateTemplates ( {
116+ filter : template => template . filename === 'discord/slashCommands' ,
117+ } )
118+ }
119+ } )
100120
101121 nuxt . hook ( 'close' , ( ) => {
102122 listener ?. server . close ( )
@@ -203,3 +223,21 @@ export function createWebSocket() {
203223 } ,
204224 }
205225}
226+
227+ async function generateDynamicCommandBuild ( file : string , config : RollupConfig , ctx : NuxtDiscordContext ) {
228+ let bundle : RollupBuild
229+ try {
230+ bundle = await rollup ( { ...config , input : file } )
231+ const { output } = await bundle . generate ( { ...config . output , sourcemap : false } )
232+ mkdirSync ( path . join ( ctx . nuxt . options . buildDir , 'discord' , 'commands' ) , { recursive : true } )
233+ writeFileSync ( file
234+ . replace ( ctx . resolve . root ( ctx . nuxt . options . rootDir ) , ctx . nuxt . options . buildDir )
235+ . replace ( '.ts' , '.mjs' ) , output [ 0 ] . code , 'utf-8' )
236+ }
237+ catch ( error ) {
238+ ctx . logger . error ( `Error processing command file ${ file } :` , error )
239+ return
240+ }
241+
242+ await bundle . close ( )
243+ }
0 commit comments