Plugin tools
Keeping state through reloads, updates, optional permissions, secrets, settings, calls between plugins, libraries, assets, translations, metrics and tests.
Functions
plugin.keep(default)
A table that survives a reload while ForgeCast stays open: local state = plugin.keep({ score = 0 })
gives back what it held when the plugin last stopped (or default the first time).
default:table
Returns table
plugin.on_update(fn)
fn(old_version, new_version) once after the plugin was updated (not on its first start).
fn:fun(old: string, new: string)
plugin.has(permission)
Whether the plugin may use a permission right now.
permission:string
Returns boolean
plugin.request(permission, why, callback)
Ask the streamer for one of the permissions in "optional_permissions", saying why. The callback gets true when they allow it (at once if they already had).
Name
Type
plugin.secret(name, value)
A secret (an API key, a token) kept in the Windows Credential Manager, not in a file:
plugin.secret("api_key", value) keeps it, plugin.secret("api_key") reads it, nil removes it.
name:stringvalue:string|nil, optional
Returns string?
plugin.config(spec)
Settings from a description: draws the settings panel on the plugin's card, checks what is typed, saves it and returns a table that always holds the current values. (and "storage" to remember them).
spec:{ title: string?, fields: ConfigField[], on_change: fun(cfg: table)? }
Returns table
bus.handle(method, fn)
Answer other plugins' bus.call for a method: return the result (an error is sent back as the error).
method:stringfn:fun(args: any, from: string): any
Returns integer id
bus.call(plugin_id, method, args, callback)
Call a method another plugin handles. callback(result), or (nil, why) (also after 10 s
without an answer).
Name
Type
Returns integer id
lib.require(name)
A module of a library plugin listed in "libraries": "chat-tools" loads its init.lua, "chat-tools/text.words" its text/words.lua.
name:string
Returns any
assets.url(path)
The address of a picture, sound or font in the plugin's folder, for ui.image and overlays.
path:string. "img/logo.png"
Returns string
i18n.locale()
The app's language ("en", "hi-IN"…).
Returns string
i18n.t(key, vars)
A text from locales/<language>.json in the app's language (then English), with {name}
filled in from vars. Nested keys use dots: "menu.start".
key:stringvars:table, optional
Returns string
log.metric(name, value)
Graph a number in the Inspector (the last 120 values, up to 20 names).
name:stringvalue:number
log.table(rows, columns)
Rows of tables as an aligned table in the console.
rows:table[]columns:string[], optional
Returns string
log.inspect(value)
Any value, nested tables and all, readably in the console.
value:any
Returns string
util.inspect(value)
A value as readable text (what log.inspect prints).
value:any
Returns string
test.case(name, fn)
A test: it passes unless it errors (test.expect and test.equal error when they fail).
name:stringfn:fun()
test.async(name, fn)
A test that waits: call done() when it passed, or done("why") when it failed (5 s at most).
name:stringfn:fun(done: fun(error?: string))
test.expect(cond, msg)
Fail the test (with msg) unless cond is true.
cond:anymsg:string, optional
test.equal(got, want, msg)
Equal, tables compared field by field.
Name
Type
test.chat(text, spec)
A made-up chat line delivered to this plugin's own handlers (not to other plugins).
text:stringspec:{ author: string, kind: string, amount: number, currency: string, member: boolean, mod: boolean, owner: boolean, count: integer }, optional
test.run(on_done)
Run every test, one after the other; the console says how each went (also "Run tests" in the Test environment).
on_done:fun(passed: integer, failed: integer), optional
test.results()
How the last run went.
Returns { name: string, ok: boolean, error: string? }[]?
Types
Open a type to see its fields; type names above link here.

