Skip to content

Commit 543365f

Browse files
committed
refactor: move hookable defines to rr/hookable
1 parent d651b43 commit 543365f

File tree

2 files changed

+74
-64
lines changed

2 files changed

+74
-64
lines changed

libs/roo-rocket/src/cli-entry.ts

Lines changed: 3 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,8 @@
11
#!/usr/bin/env node
22

3-
import type { UnpackOptions } from 'config-rocket/cli'
4-
import { readFile } from 'node:fs/promises'
53
import { defineCommand, runMain } from 'citty'
64
import { getValidGhRepoReleaseAssets, promptSelectGhAsset, unpackFromUrl } from 'config-rocket/cli'
7-
import defu from 'defu'
8-
import { createHooks } from 'hookable'
9-
import { logger } from '~/helpers/logger'
10-
11-
// Main hookable instance
12-
const rooRocketUnpackHookable = createHooks() as NonNullable<UnpackOptions['hookable']>
13-
14-
// Hook to only allow specific file patterns
15-
rooRocketUnpackHookable.hook('onFrameFile', ({ filePath, skipFile }) => {
16-
if (!/^\.(?:roomodes|roo\/.*)$/.test(filePath)) {
17-
logger.warn(`Unallowed frame structure found: ${filePath}, skipping...`)
18-
skipFile()
19-
}
20-
})
21-
22-
// Hooks to handle .roomodes merging
23-
rooRocketUnpackHookable.hook('onFileOutput', async (state) => {
24-
if (state.filePath.endsWith('.roomodes')) {
25-
state.mergeType = 'json'
26-
state.isValidFileToMerge = true
27-
}
28-
})
29-
rooRocketUnpackHookable.hook('onFileOutputJsonMerge', async (state) => {
30-
if (state.filePath.endsWith('.roomodes')) {
31-
const existingModeSlugs = new Set<string>()
32-
const oldData = JSON.parse(await readFile(state.filePath, 'utf8'))
33-
const newData = JSON.parse(state.data)
34-
const mergedData = defu(newData, oldData)
35-
const dedupedModes = mergedData.customModes.filter((mode: any) => {
36-
if (existingModeSlugs.has(mode.slug)) {
37-
logger.info(`Present roomode entry overwritten: ${mode.slug}`)
38-
return false
39-
}
40-
41-
return existingModeSlugs.add(mode.slug) && true
42-
})
43-
44-
const result = { ...mergedData, customModes: dedupedModes }
45-
state.mergeResult = JSON.stringify(result, null, 2)
46-
}
47-
})
48-
49-
// Hook to handle mcp.json merging
50-
rooRocketUnpackHookable.hook('onFileOutputJsonMerge', async (state) => {
51-
if (state.filePath.endsWith('.roo/mcp.json')) {
52-
const oldData = JSON.parse(await readFile(state.filePath, 'utf8'))
53-
const newData = JSON.parse(state.data)
54-
const mergedData = structuredClone(newData)
55-
for (const [key, value] of Object.entries(oldData.mcpServers)) {
56-
if (key in mergedData.mcpServers) {
57-
logger.info(`Present mcp server entry overwritten: ${key}`)
58-
continue
59-
}
60-
61-
mergedData.mcpServers[key] = value
62-
}
63-
64-
state.mergeResult = JSON.stringify(mergedData, null, 2)
65-
}
66-
})
5+
import { hookable } from '~/rr/hookable'
676

687
const main = defineCommand({
698
meta: {
@@ -114,7 +53,7 @@ const main = defineCommand({
11453
return await unpackFromUrl(url, {
11554
nonAssemblyBehavior,
11655
sha256,
117-
hookable: rooRocketUnpackHookable,
56+
hookable,
11857
})
11958
}
12059

@@ -138,7 +77,7 @@ const main = defineCommand({
13877
return await unpackFromUrl(selectedAsset.browser_download_url, {
13978
nonAssemblyBehavior,
14079
sha256,
141-
hookable: rooRocketUnpackHookable,
80+
hookable,
14281
})
14382
},
14483
})

libs/roo-rocket/src/rr/hookable.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* @module rr/hookable
3+
* @description This module contains the main hookable instance of Roo Rocket, with default hooks registered.
4+
*/
5+
6+
import type { UnpackOptions } from 'config-rocket/cli'
7+
import { readFile } from 'node:fs/promises'
8+
import defu from 'defu'
9+
import { createHooks } from 'hookable'
10+
import { logger } from '~/helpers/logger'
11+
12+
/**
13+
* Main hookable instance of Roo Rocket, with default hooks registered.
14+
*/
15+
const hookable = createHooks() as NonNullable<UnpackOptions['hookable']>
16+
17+
// Hook to only allow specific file patterns
18+
hookable.hook('onFrameFile', ({ filePath, skipFile }) => {
19+
if (!/^\.(?:roomodes|roo\/.*)$/.test(filePath)) {
20+
logger.warn(`Unallowed frame structure found: ${filePath}, skipping...`)
21+
skipFile()
22+
}
23+
})
24+
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+
}
43+
44+
return existingModeSlugs.add(mode.slug) && true
45+
})
46+
47+
const result = { ...mergedData, customModes: dedupedModes }
48+
state.mergeResult = JSON.stringify(result, null, 2)
49+
}
50+
})
51+
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
62+
}
63+
64+
mergedData.mcpServers[key] = value
65+
}
66+
67+
state.mergeResult = JSON.stringify(mergedData, null, 2)
68+
}
69+
})
70+
71+
export { hookable }

0 commit comments

Comments
 (0)