@@ -10,62 +10,69 @@ import { createHooks } from 'hookable'
1010import { logger } from '~/helpers/logger'
1111
1212/**
13- * Main hookable instance of Roo Rocket, with default hooks registered.
13+ * Workaround for unjs/hookable#116
1414 */
15- const hookable = createHooks ( ) as NonNullable < UnpackOptions [ 'hookable' ] >
15+ export function createHookable ( ) : NonNullable < UnpackOptions [ 'hookable' ] > {
16+ const instance = createHooks ( ) as NonNullable < UnpackOptions [ 'hookable' ] >
1617
17- // Hook to only allow specific file patterns
18- hookable . hook ( 'onFrameFile' , ( { filePath, skipFile } ) => {
19- if ( ! / ^ \. (?: r o o m o d e s | r o o \/ .* ) $ / . test ( filePath ) ) {
20- logger . warn ( `Unallowed frame structure found: ${ filePath } , skipping...` )
21- skipFile ( )
22- }
23- } )
18+ // Hook to only allow specific file patterns
19+ instance . hook ( 'onFrameFile' , ( { filePath, skipFile } ) => {
20+ if ( ! / ^ \. (?: r o o m o d e s | r o o \/ .* ) $ / . test ( filePath ) ) {
21+ logger . warn ( `Unallowed frame structure found: ${ filePath } , skipping...` )
22+ skipFile ( )
23+ }
24+ } )
2425
25- // Hooks to handle .roomodes merging
26- hookable . hook ( 'onFileOutput' , async ( state ) => {
27- if ( state . filePath . endsWith ( '.roomodes' ) ) {
28- state . mergeType = 'json'
29- state . isValidFileToMerge = true
30- }
31- } )
32- hookable . hook ( 'onFileOutputJsonMerge' , async ( state ) => {
33- if ( state . filePath . endsWith ( '.roomodes' ) ) {
34- const existingModeSlugs = new Set < string > ( )
35- const oldData = JSON . parse ( await readFile ( state . filePath , 'utf8' ) )
36- const newData = JSON . parse ( state . data )
37- const mergedData = defu ( newData , oldData )
38- const dedupedModes = mergedData . customModes . filter ( ( mode : any ) => {
39- if ( existingModeSlugs . has ( mode . slug ) ) {
40- logger . info ( `Present roomode entry overwritten: ${ mode . slug } ` )
41- return false
42- }
26+ // Hooks to handle .roomodes merging
27+ instance . hook ( 'onFileOutput' , async ( state ) => {
28+ if ( state . filePath . endsWith ( '.roomodes' ) ) {
29+ state . mergeType = 'json'
30+ state . isValidFileToMerge = true
31+ }
32+ } )
33+ instance . hook ( 'onFileOutputJsonMerge' , async ( state ) => {
34+ if ( state . filePath . endsWith ( '.roomodes' ) ) {
35+ const existingModeSlugs = new Set < string > ( )
36+ const oldData = JSON . parse ( await readFile ( state . filePath , 'utf8' ) )
37+ const newData = JSON . parse ( state . data )
38+ const mergedData = defu ( newData , oldData )
39+ const dedupedModes = mergedData . customModes . filter ( ( mode : any ) => {
40+ if ( existingModeSlugs . has ( mode . slug ) ) {
41+ logger . info ( `Present roomode entry overwritten: ${ mode . slug } ` )
42+ return false
43+ }
4344
44- return existingModeSlugs . add ( mode . slug ) && true
45- } )
45+ return existingModeSlugs . add ( mode . slug ) && true
46+ } )
4647
47- const result = { ...mergedData , customModes : dedupedModes }
48- state . mergeResult = JSON . stringify ( result , null , 2 )
49- }
50- } )
48+ const result = { ...mergedData , customModes : dedupedModes }
49+ state . mergeResult = JSON . stringify ( result , null , 2 )
50+ }
51+ } )
5152
52- // Hook to handle mcp.json merging
53- hookable . hook ( 'onFileOutputJsonMerge' , async ( state ) => {
54- if ( state . filePath . endsWith ( '.roo/mcp.json' ) ) {
55- const oldData = JSON . parse ( await readFile ( state . filePath , 'utf8' ) )
56- const newData = JSON . parse ( state . data )
57- const mergedData = structuredClone ( newData )
58- for ( const [ key , value ] of Object . entries ( oldData . mcpServers ) ) {
59- if ( key in mergedData . mcpServers ) {
60- logger . info ( `Present mcp server entry overwritten: ${ key } ` )
61- continue
53+ // Hook to handle mcp.json merging
54+ instance . hook ( 'onFileOutputJsonMerge' , async ( state ) => {
55+ if ( state . filePath . endsWith ( '.roo/mcp.json' ) ) {
56+ const oldData = JSON . parse ( await readFile ( state . filePath , 'utf8' ) )
57+ const newData = JSON . parse ( state . data )
58+ const mergedData = structuredClone ( newData )
59+ for ( const [ key , value ] of Object . entries ( oldData . mcpServers ) ) {
60+ if ( key in mergedData . mcpServers ) {
61+ logger . info ( `Present mcp server entry overwritten: ${ key } ` )
62+ continue
63+ }
64+
65+ mergedData . mcpServers [ key ] = value
6266 }
6367
64- mergedData . mcpServers [ key ] = value
68+ state . mergeResult = JSON . stringify ( mergedData , null , 2 )
6569 }
70+ } )
6671
67- state . mergeResult = JSON . stringify ( mergedData , null , 2 )
68- }
69- } )
72+ return instance
73+ }
7074
71- export { hookable }
75+ /**
76+ * Main hookable instance of Roo Rocket, with default hooks registered.
77+ */
78+ export const hookable : NonNullable < UnpackOptions [ 'hookable' ] > = createHookable ( )
0 commit comments