
Security News
Feross on TBPN: How North Korea Hijacked Axios
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.
@revenge-mod/devtools-shared
Advanced tools
Shared utilities, types, and constants for Revenge Developer Tools.
Shared utilities, types, and constants for Revenge Developer Tools.
The shared package provides common functionality used by both the client and server packages:
The package exports four main modules:
import { LogLevel, MessageType, PROTOCOL_VERSION, DEFAULT_SETTINGS } from '@revenge-mod/devtools-shared/constants'
import type { Message, LogMessage, RunMessage, HelloMessage, HiMessage, Settings } from '@revenge-mod/devtools-shared/types'
import { serialize, deserialize, createDepthLimitedProxy } from '@revenge-mod/devtools-shared/serializer'
import { logger, createClientLogger, setPrompt, clearPromptLine } from '@revenge-mod/devtools-shared/logger'
LogLevelDefines the available log levels:
export const LogLevel = {
Debug: 0, // Verbose debug information
Default: 1, // Normal logs
Warn: 2, // Warning messages
Error: 3, // Error messages
} as const
MessageTypeDefines the WebSocket message types:
export const MessageType = {
Hello: 1, // Client introduces itself
Hi: 2, // Server acknowledges connection
Log: 3, // Client sends logs
Run: 4, // Server executes code
} as const
PROTOCOL_VERSIONCurrent protocol version (2). Used for client-server compatibility checks.
DEFAULT_SETTINGSDefault configuration for client and server:
export const DEFAULT_SETTINGS: Settings = {
client: {
log: {
level: LogLevel.Default,
inspectDepth: 2,
interceptConsole: true,
},
},
server: {
watch: {
command: false,
},
},
}
MessageBase message interface:
interface Message {
type: MessageType
data?: any
}
LogMessageMessage for sending logs to the server:
interface LogMessage extends Message {
type: MessageType<'Log'>
data: {
level: LogLevel
message: any[]
}
}
RunMessageMessage for executing code on the client:
interface RunMessage extends Message {
type: MessageType<'Run'>
data: {
code: string
mappings: Record<string, string> // Variable name -> path in client scope
}
}
HelloMessageInitial client handshake:
interface HelloMessage extends Message {
type: MessageType<'Hello'>
data: {
version: number
info?: string // Optional client description
}
}
HiMessageServer response to handshake:
interface HiMessage extends Message {
type: MessageType<'Hi'>
data: {
version: number
supported: boolean // Whether client version is compatible
settings: ClientSettings
}
}
ClientSettingsConfiguration for the client:
interface ClientSettings {
log: {
level: LogLevel // Minimum log level
interceptConsole: boolean // Whether to intercept console
inspectDepth: number // Max depth for object inspection
}
}
ServerSettingsConfiguration for the server:
interface ServerSettings {
watch: {
command: string | false // Command to run on file changes
}
}
SettingsCombined settings:
interface Settings {
client: ClientSettings
server: ServerSettings
}
The serializer uses superjson with custom transformers for React Native compatibility.
serialize(value: any): stringSerialize a value to a JSON string with support for:
Symbol.toStringTagimport { serialize } from '@revenge-mod/devtools-shared/serializer'
const data = { fn: () => {}, sym: Symbol('test') }
const json = serialize(data)
deserialize<T>(json: string): TDeserialize a JSON string back to its original value:
import { deserialize } from '@revenge-mod/devtools-shared/serializer'
const data = deserialize<MyType>(json)
createDepthLimitedProxy<T>(obj: T, maxDepth?: number, currentDepth?: number): TCreate a proxy that limits object traversal depth to prevent excessive serialization:
import { createDepthLimitedProxy } from '@revenge-mod/devtools-shared/serializer'
const obj = { deep: { nested: { structure: { here: 'value' } } } }
const limited = createDepthLimitedProxy(obj, 2)
// Accessing beyond depth 2 returns special markers:
// limited.deep.nested.structure // Returns [Object]
The proxy handles:
[Object] at max depth[Function: name] at max depth[Getter] at max depth[Setter] at max depth[Getter/Setter] at max depthThese markers are rendered with colors in Node.js environments.
Server-side logging utilities that preserve the terminal prompt.
loggerMain logger instance with colored output:
import { logger } from '@revenge-mod/devtools-shared/logger'
logger.debug('Debug message') // Plain output
logger.log('Normal message') // Plain output
logger.info('Info message') // ℹ️ prefix
logger.warn('Warning') // ⚠️ prefix
logger.error('Error') // 🛑 prefix
logger.success('Success') // ✅ prefix
logger.server('Server message') // [SERVER] prefix in magenta
logger.client('a1b2c3d4', 'Client') // [a1b2c3d4] prefix in cyan
createClientLogger(id: string)Create a logger instance for a specific client:
import { createClientLogger } from '@revenge-mod/devtools-shared/logger'
const clientLog = createClientLogger('a1b2c3d4')
clientLog.log('Message') // [a1b2c3d4] Message
clientLog.warn('Warning') // ⚠️ [a1b2c3d4] Warning
clientLog.error('Error') // 🛑 [a1b2c3d4] Error
setPrompt(prompt: string, line?: string)Set the current prompt for preservation during logging:
import { setPrompt } from '@revenge-mod/devtools-shared/logger'
setPrompt('> ', 'user input')
clearPromptLine()Clear the current input line:
import { clearPromptLine } from '@revenge-mod/devtools-shared/logger'
clearPromptLine()
The serializer handles complex JavaScript objects:
// Functions are preserved by name
const fn = function namedFunction() {}
serialize({ fn }) // Preserves function name
// Symbols are preserved
const sym = Symbol('description')
serialize({ sym }) // Preserves symbol description
// Special objects maintain their string representation
const map = new Map()
serialize({ map }) // Preserves [object Map] representation
Prevents excessive serialization and circular references:
const circular = { a: {} }
circular.a.b = circular
const proxy = createDepthLimitedProxy(circular, 2)
// Access beyond depth returns markers instead of recursing infinitely
The logger clears and restores the terminal prompt when logging:
// User is typing: "> hello world"
logger.log('New message')
// Output:
// New message
// > hello world (prompt restored)
This project is licensed under CC0 1.0. See LICENSE for more details.
FAQs
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.

Security News
OpenSSF has issued a high-severity advisory warning open source developers of an active Slack-based campaign using impersonation to deliver malware.

Research
/Security News
Malicious packages published to npm, PyPI, Go Modules, crates.io, and Packagist impersonate developer tooling to fetch staged malware, steal credentials and wallets, and enable remote access.