@iniquitybbs/core
v3.0.86
Published
Core BBS runtime library for building bulletin board systems with Iniquity.
Readme
@iniquitybbs/core
The core runtime library for building modern BBS applications with Iniquity.
Overview
@iniquitybbs/core provides everything you need to build a bulletin board system using a simple, declarative API.
import { bbs, screen } from "@iniquitybbs/core"Installation
npm install @iniquitybbs/coreQuick Start
import { bbs, screen } from "@iniquitybbs/core"
// Set terminal resolution (default: 132x37)
screen.setResolution(132, 37)
// Register menus
bbs.menu("main", {
art: "main_menu.ans",
layout: "two-column",
items: [
{ key: "M", label: "Messages", goto: "messages" },
{ key: "F", label: "Files", goto: "files" },
{ key: "G", label: "Goodbye", action: "quit" }
]
})
// Start the BBS
bbs.start(async () => {
await bbs.art("welcome.ans", { clearScreen: true, pauseAfter: true })
await bbs.showMenu("main")
})Architecture
┌─────────────────────────────────────────────────────┐
│ BBS Layer │
│ The Interface You Use │
│ │
│ • bbs object (declarative API) │
│ • screen utilities (dimensions, centering) │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Runtime Layer │
│ Everything That Makes It Work │
│ │
│ • Core: Runtime coordinator │
│ • Components: Menu, Frame, Reactor, Events │
│ • Data: User, Group, Config, Network │
│ • Graphics: Graphic, Artwork, Avatar, Sixel, XBin │
│ • I/O: Output abstraction, ANSI utilities │
│ • MCI: Pipe codes, @-codes, control codes │
│ • Utilities: String utils, decorators │
└─────────────────────────────────────────────────────┘BBS Layer = What you use to build your BBS
Runtime Layer = The engine that powers it (available for advanced use)
BBS API Reference
screen - Terminal Utilities
| Property/Method | Description |
|-----------------|-------------|
| screen.width | Terminal width (default: 132) |
| screen.height | Terminal height (default: 37) |
| screen.setResolution(w, h) | Set terminal dimensions |
| screen.centerX(width) | Calculate X to center element horizontally |
| screen.centerY(height) | Calculate Y to center element vertically |
| screen.center(w, h) | Returns { x, y } for centered positioning |
| screen.midX | Horizontal center point |
| screen.midY | Vertical center point |
bbs - Core BBS Object
Lifecycle
bbs.start(callback: () => Promise<void>): voidMenu System
bbs.menu(name: string, options: BBSMenuOptions): void
await bbs.showMenu(name: string): Promise<string>Menu Options:
art- Artwork filenamelayout- 'single' or 'two-column'items- Array of menu itemsprompt- Custom prompt textpromptX,promptY- Prompt positioncol1X,col1Y,col2X,col2Y- Column positionsitemFormat- Format string
Example:
bbs.menu("main", {
art: "main.ans",
layout: "two-column",
items: [
{ key: "M", label: "Messages", goto: "messages" },
{ key: "Q", label: "Quit", action: "quit" }
]
})Artwork Rendering
await bbs.art(filename: string, options?: BBSArtOptions): Promise<void>Options: clearScreen, display, speed, data, center, x, y, pauseAfter
Popups & Dialogs
await bbs.popup(title: string, message: string, options?): Promise<string>
await bbs.choice(title: string, choices: BBSChoiceOption[], options?): Promise<string>
await bbs.dataPopup<T>(title: string, items: T[], formatter, options?): Promise<void>
bbs.frame(title: string, options?): IQFrameUser Management
await bbs.loginForm(): Promise<IQUser | null>
await bbs.registerForm(): Promise<IQUser | null>
bbs.user(handle: string): IQUser
bbs.users(): IQUserList
bbs.setCurrentUser(user: IQUser | null): void
bbs.getCurrentUser(): IQUser | null
bbs.isLoggedIn(): boolean
bbs.group(name: string): IQGroup
bbs.groups(): IQGroupListEvent System
bbs.on(event: string, handler: IQEventHandler, options?): () => void
bbs.once(event: string, handler: IQEventHandler): () => void
bbs.off(event: string, handler?: IQEventHandler): void
bbs.emit(event: string, data?: any, source?: string): void
await bbs.emitSync(event: string, data?: any, source?: string): Promise<void>Basic I/O
bbs.say(text: string): void
await bbs.ask(prompt: string): Promise<string>
await bbs.pause(prompt?: string): Promise<string>
await bbs.wait(ms: number): Promise<void>
bbs.cls(): void
bbs.hangup(): voidServer Info
bbs.getOnlineUsers(): SessionInfo[]
bbs.getOnlineCount(): number
bbs.getServerInfo(): ServerInfo | nullRuntime Layer Reference
For advanced users who need direct access to runtime components.
Core (core.ts)
Runtime - Component coordinator (used internally by executor):
import { Runtime, getGlobalRuntime } from "@iniquitybbs/core"
const runtime = getGlobalRuntime()
runtime.say("Direct runtime access")Artwork (artwork.ts)
Artwork - ANSI rendering with SAUCE metadata:
import { Artwork } from "@iniquitybbs/core"
const art = new Artwork('assets', output)
await art.render({
filename: 'welcome.ans',
display: 'line',
speed: 30,
data: { USERNAME: 'SysOp' }
})String Utilities (string-utils.ts)
Opt-in functions (no global pollution):
import { colorText, centerText, stripAnsi, visibleLength } from "@iniquitybbs/core"
const text = centerText(colorText("Hello", "cyan"), 80)Components
IQMenu (menu.ts) - Command-driven menus:
import { IQMenu } from "@iniquitybbs/core"
const menu = new IQMenu(options, output, artworkFactory)
menu.addItem({ key: 'M', label: 'Messages', x: 10, y: 12 })
await menu.show()IQFrame (frame.ts) - Bordered UI elements:
import { IQFrame, screen } from "@iniquitybbs/core"
const frame = new IQFrame({
x: screen.centerX(50),
y: screen.centerY(15),
width: 50,
height: 15,
color: 'cyan',
border: 'double'
}, output)
frame.open()
frame.say('Content')
await frame.input('Prompt: ')
frame.close()IQReactor (reactor.ts) - Reactive data:
import { IQReactor } from "@iniquitybbs/core"
const data = IQReactor({
count: 0,
message: (state) => `Count: ${state.count}`
})IQEventBus (events.ts) - Event system:
import { events } from "@iniquitybbs/core"
events.on('user:login', (event) => console.log(event.data))
events.emit('custom:event', { data: 'value' })Data Management
User (user.ts):
import { IQUser, UserAccessLevel } from "@iniquitybbs/core"
const user = new IQUser({ handle: 'SysOp' })
if (user.exists() && user.login(password)) {
console.log(user.stats.totalCalls)
}Group (group.ts):
import { IQGroup } from "@iniquitybbs/core"
const group = new IQGroup('sysops')
group.addMember('SysOp')
group.setPermission('canModerate', true)Config (config.ts):
import { getConfig } from "@iniquitybbs/core"
const config = getConfig()
config.set('bbs.name', 'My BBS')
config.save()Graphics & Rendering
Graphic (graphic.ts) - In-memory ANSI buffer:
import { Graphic, makeAttr, CGA } from "@iniquitybbs/core"
const graphic = new Graphic({ width: 80, height: 25 })
graphic.setData(x, y, 'A', makeAttr(CGA.FG_CYAN, CGA.BG_BLACK))
graphic.draw(output, 1, 1)Avatar (avatar.ts), CTerm (cterm.ts), Sixel (sixel.ts), XBin (xbin.ts) - Specialized graphics support.
I/O & ANSI
ANSI (ansi.ts) - Escape sequences:
import { ANSI, CGA } from "@iniquitybbs/core"
ANSI.gotoxy(10, 5)
ANSI.clearScreen()
ANSI.color('bright cyan')
ANSI.cursor.hide()IQOutput (output.ts) - Abstract I/O interface for session-agnostic core.
MCI System
Pipe Codes - Colors: |00 through |23
@-Codes - Dynamic data: @USER@, @DATE@, @BBS@, etc.
Control Codes - Commands: |CS (clear), |PA (pause), |PO#,# (position)
Position Markers - ^X01 through ^X99
import { MCIProcessor } from "@iniquitybbs/core"
const mci = new MCIProcessor()
mci.setCustom('CUSTOM', 'value')
const result = mci.process('Hello |15@USER@|07!')Decorators
Module Decorators (decorators.ts) - For runtime organization:
@IQModule({ name: 'mymodule', basepath: 'assets' })
@IQModuleRuntime({ debug: true })Utility Decorators (decorators-runtime.ts) - For class enhancement:
import { Cached, Measure, Validate, Lifecycle, Transaction, Synchronized } from "@iniquitybbs/core"
class MyComponent {
@Cached({ ttl: 5000 })
@Measure()
getData() { /* ... */ }
}Available: @Cached, @Measure, @Validate, @Lifecycle, @Transaction, @Synchronized, @Retry, @Timeout, @Debounce, @Throttle
License
MIT
