Modules (require)

Load a module with require('name'). NodeAmiga looks up modules in this order:

  1. Built-in native modules (implemented in C inside NodeAmiga)
  2. Embedded bundle (when running from a -compile'd standalone executable)
  3. Relative path (./file.js / ../file.js)
  4. Absolute AmigaOS path (anything containing :, e.g. SYS:libs/foo.js)
  5. Search path: PROGDIR:libs/, LIBS:node/, libs/, PROGDIR:modules/, current dir — tries both name.js and name/index.js

ES-module syntax (import / export) is also supported and uses the same resolution logic.

Modules on this page

fs — files & directories

var fs = require('fs');

Synchronous filesystem via AmigaOS DOS. All operations take AmigaOS-style paths (RAM:foo.txt, SYS:s/startup-sequence).

fs.readFileSync(path, encoding?)

Returns the file contents. With encoding: 'utf8' returns a string; otherwise a Buffer.

fs.writeFileSync(path, data)

Write a string or Buffer to disk. Overwrites existing files.

fs.appendFileSync(path, data)

Append to an existing file (or create).

fs.existsSync(path) → boolean
fs.unlinkSync(path)

Delete a file.

fs.renameSync(oldPath, newPath)
fs.statSync(path)

Returns {size, isFile(), isDirectory()}. Throws Error with ENOENT if the path doesn't exist.

fs.readdirSync(path)

Returns an array of entry names (no . / ..). Uses Lock+Examine+ExNext.

fs.mkdirSync(path) / fs.rmdirSync(path)
fs.copyFileSync(src, dst)

4 KB buffered copy.

fs.readFile(path, callback) / fs.writeFile(path, data, callback)

Callback-style versions. Still synchronous internally on Amiga — the callback runs before the call returns. Useful for Node.js portability.

fs.createReadStream(path, {highWaterMark?})

Returns an EventEmitter emitting 'data' (Buffers) and 'end'. Note: reads the whole file in one sweep — highWaterMark only chooses chunk size for the emitted data events.

fs.createWriteStream(path)

EventEmitter with write(chunk), end(), 'finish' event, bytesWritten.

RAM: is your friend

The Amiga RAM disk (RAM:) is blazing fast and perfect for temp files, caches, and small databases. Use it freely for anything that doesn't need to survive a reboot.

http — HTTP client & server

var http = require('http');

HTTP/1.0 client and server over bsdsocket.library. HTTPS requires AmiSSL (see below).

Client

http.get(url) → {statusCode, body, headers}

Synchronous GET. Follows up to 5 redirects automatically (301/302/303/307/308). Body is always a string.

http.post(url, body, contentType?) → {statusCode, body, headers}

Synchronous POST. body is a string or Buffer. Default content type: application/x-www-form-urlencoded.

http.request(urlOrOptions) → {statusCode, body, headers}

Generic request. options may be {url, method, body, headers}.

Server

http.createServer(handler) → server

Create a server. handler(req, res) is called for each request.

server.listen(port, callback?)

Start accepting connections. Handles up to 8 concurrent clients (non-blocking via WaitSelect). Stops on Ctrl+C.

In the handler:

HTTPS / AmiSSL

http.hasSSL() / http.sslAvailable()

Returns true if HTTPS is available at runtime. Requires NodeAmiga built with -DENABLE_AMISSL AND AmiSSL 5+ installed on the system.

10-second socket timeout

Both send and receive have a 10-second timeout. Slow or unresponsive servers will fail with a connection error. There's currently no way to override this from JavaScript.

net — raw TCP

Currently exposes the same get/request/createServer as http. For a dedicated low-level TCP API, use the FFI module to call bsdsocket.library directly.

buffer

var { Buffer } = require('buffer');  // also available as global

Same Buffer as described in Global API → Buffer. The module export additionally provides Buffer as a named property for Node.js portability.

os — system info

var os = require('os');
os.platform() → "amigaos"
os.arch() → "m68k"
os.type() → "AmigaOS"
os.version() → "39.x" / "45.x" / etc.

Kickstart version from ExecBase->lib_Version.

os.release() → same as version()
os.hostname() → $HOSTNAME or "amiga"
os.tmpdir() → "T:"
os.homedir() → "SYS:"
os.freemem() → bytes

Available memory, from AvailMem(MEMF_ANY).

os.totalmem() → bytes

Returns the same value as freemem() — AmigaOS 2.x has no API for the total installed memory.

os.cpus() → array

Returns a single-element array [{ model, speed }]. Model comes from SysBase->AttnFlags (68000/68010/68020/68030/68040/68060). Speed is always 0 (no portable way to read accelerator clock).

os.uptime() → 0

Not implemented; AmigaOS has no portable uptime API.

os.endianness() → "BE"
os.userInfo() → {username, uid, gid, homedir, shell}

Hardcoded: {username:"amiga", uid:-1, gid:-1, homedir:"SYS:", shell:""}.

os.networkInterfaces() → {}

Empty — TCP/IP stacks differ; NodeAmiga doesn't enumerate them.

Constants: os.EOL = "\n", os.devNull = "NIL:", os.constants.signals.SIGINT=2, os.constants.signals.SIGTERM=15.

path — path manipulation

var path = require('path');

Uses AmigaOS conventions: absolute paths contain : (e.g. SYS:foo/bar), relative don't.

path.basename(p, ext?)

Last segment. Optional ext strips trailing extension.

path.dirname(p)

Everything except the last segment.

path.extname(p)

The .ext part (or empty string).

path.join(...parts)

Concatenate with /. Any part containing : resets the accumulator.

path.resolve(...parts)

Like join but always produces an absolute-looking result.

path.normalize(p)

Collapse .. and ..

path.isAbsolute(p)

Returns true if p contains a colon (Amiga absolute).

path.parse(p) → {root, dir, base, ext, name}
path.format(pathObj)
path.relative(from, to)

Constants: path.sep = '/', path.delimiter = ';'.

url — URL parsing

var url = require('url');

Legacy API

url.parse(str, parseQueryString?)

Returns {protocol, slashes, auth, hostname, port, host, pathname, search, query, hash, path, href}. With parseQueryString=true, query is a parsed object (via querystring.parse).

url.format(urlObj)

Rebuilds a URL string from a parse result.

url.resolve(from, to)

Resolve a relative URL against a base.

WHATWG URL

new URL(input, base?)

Modern URL class. .protocol, .hostname, .port, .pathname, .search, .hash, .host, .origin, .href, .username, .password, .searchParams, .toString(), .toJSON().

Does NOT throw on invalid input — it parses permissively and returns a partial object (spec-divergent).

new URLSearchParams(init?)

append, delete, get, getAll, has, set, sort, toString, forEach, keys, values, entries, .size. Note: keys/values/entries return arrays, not iterators.

querystring

var qs = require('querystring');
qs.parse(str, sep='&', eq='=', {maxKeys?}) → object
qs.stringify(obj, sep='&', eq='=') → string
qs.escape(str) / qs.unescape(str)

Standard Node.js querystring semantics: repeated keys become arrays on parse; arrays produce multiple key=value pairs on stringify.

events — EventEmitter

var EventEmitter = require('events');
var bus = new EventEmitter();
bus.on('ready', () => console.log('go!'));
bus.emit('ready');

Methods: on(event, fn), off(event, fn), once(event, fn), emit(event, ...args), removeListener, removeAllListeners(event?), listenerCount(event), listeners(event), setMaxListeners(n), eventNames(), prependListener, prependOnceListener. Aliases: addListener = on.

Emit passes up to 5 args

emit(event, a, b, c, d, e) passes the first five arguments to each listener. Beyond that, arguments are discarded. (Node.js has no such limit.)

stream

var stream = require('stream');

Pure-JS implementations of Readable, Writable, Duplex, Transform, PassThrough, plus helpers pipeline(...streams, cb) and finished(stream, cb).

var r = new stream.Readable({ read() {} });
r.on('data', chunk => console.log(chunk));
r.push('hello');
r.push(null); // end

Supports pipe(dest), backpressure, highWaterMark (default 16), cork/uncork on Writable.

util

var util = require('util');
util.format(fmt, ...args)

printf-style formatter. Supports %s, %d, %i, %f, %j (JSON), %o/%O (inspect), %%.

util.inspect(obj, {depth?, showHidden?})

Pretty-print an object for debugging. Default depth 2. Truncates arrays at 100 items, objects at 50 keys.

util.inherits(ctor, superCtor)

Classic pre-ES6 inheritance helper.

util.promisify(callbackFn) → Promise-returning fn

Converts a Node-style (err, result) → callback function.

Legacy type predicates: util.isArray/isFunction/isString/isNumber/isBoolean/isNull/isUndefined/isNullOrUndefined/isObject/isPrimitive.

Also: util.noop, util.debuglog(section) (currently returns a no-op).

assert

var assert = require('assert');
assert(x > 0, 'x must be positive');

Methods: assert.ok, assert.equal/notEqual, strictEqual/notStrictEqual, deepEqual/notDeepEqual, deepStrictEqual/notDeepStrictEqual, throws(fn, expected?, msg?), doesNotThrow, fail(msg), ifError(err), match(str, re, msg?), doesNotMatch, rejects(p), doesNotReject(p).

The callable module itself behaves as assert.ok.

deepEqual is strict

assert.deepEqual currently uses the same comparator as deepStrictEqual. It won't coerce 1 == "1" to true. Use assert.equal for loose equality.

zlib

var zlib = require('zlib');
zlib.deflateSync / inflateSync / deflateRawSync / inflateRawSync / gzipSync / gunzipSync

Compress and decompress data. Input and output are strings (cast bytes through Buffer.from/toString if you need Buffers).

zlib.crc32(data) / zlib.adler32(data) → number

deflate does not actually compress

The encoder currently emits "stored" (uncompressed) DEFLATE blocks — the output is larger than the input. The decoder handles fully compressed streams correctly, so this module is useful for reading gzip/deflate data but not for producing it compactly.

crypto

var crypto = require('crypto');
var hash = crypto.createHash('sha256').update('hello').digest('hex');
crypto.createHash(algo) → hasher

Supported: 'md5' (RFC 1321), 'sha256' (FIPS 180-4). Default if omitted: sha256.

The hasher has update(data) (returns this, chainable) and digest(encoding?). Only 'hex' encoding is supported — the encoding argument is accepted but ignored for other values.

No HMAC, no ciphers — plain hash functions only.

readline

var readline = require('readline');
var rl = readline.createInterface({ prompt: '> ' });
rl.question('Name? ', name => { console.log('Hi '+name); rl.close(); });

Interface methods: question(prompt, cb), prompt(), setPrompt(str), close(), on('line', fn), on('close', fn).

No line-editing (cursor keys, history) in this module — those work in the REPL via process.stdin at a lower level. Use it for simple input prompts.

dns

var dns = require('dns');
dns.lookup(hostname, callback)

callback(err, address). Resolves a single IPv4 address.

dns.resolve(hostname, callback) / dns.resolve4(hostname, callback)

Returns an array of IPv4 addresses via callback.

dns.resolveSync(hostname) → [address, ...]

Sync version. Returns empty array if no records.

Under the hood, all of these call inet_addr/gethostbyname; the async signatures are for Node.js portability — the resolution is synchronous, the callback fires immediately.

timers (promise-based)

var timers = require('timers/promises');  // or just 'timers'
await timers.setTimeout(500, 'done');
timers.setTimeout(delay, value?)

Returns a Promise that resolves to value after delay ms.

timers.setImmediate(value?)

Alias for setTimeout(0, value).

timers.setInterval(delay)

Returns an async-iterable-like with next(), cancel(), and a then() for one-shot waiting.

string_decoder

var { StringDecoder } = require('string_decoder');

Converts Buffers to strings while handling multi-byte UTF-8 boundaries. Useful when reading a stream chunk by chunk.

new StringDecoder(encoding?) — default 'utf8'. Methods: write(buf), end(buf?). Incomplete trailing bytes are buffered internally and surfaced as a replacement character \uFFFD on end() if they never complete.

punycode

var punycode = require('punycode');
punycode.toASCII('münchen.de');   // 'xn--mnchen-3ya.de'

RFC 3492 IDN encoder/decoder: encode, decode, toASCII, toUnicode, plus ucs2.decode/ucs2.encode.

console (module), constants

var c = require('console');       // same as global console
var K = require('constants');     // POSIX errno & signal names

require('console') simply re-exports the global console object.

require('constants') exposes POSIX-ish numeric codes: signals (SIGTERM=15, ...), errno (ENOENT=2, ...), fs constants (O_RDONLY=0, O_CREAT=64, ...). Values follow BSD conventions, not Amiga IoErr codes — use them for code portability, not for comparing against actual AmigaDOS errors.

iff — IFF/ILBM/8SVX parser

var iff = require('iff');
var img = iff.parseILBM(iff.parseFile('RAM:pic.iff'));

Pure-JS parser for Amiga's native Interchange File Format. Handles ILBM images and 8SVX audio in particular.

iff.parseFile(path) / iff.parse(buffer)

Returns a tree: {type, subType, length, chunks: [...]}. Each chunk has id, length, offset, data (array of bytes), and optionally nested chunks for FORM/LIST/CAT.

iff.findChunk(tree, id) / iff.findChunks(tree, id)

Depth-first chunk search.

iff.parseBMHD(data) → {width, height, numPlanes, compression, ...}

Parse an ILBM bitmap header.

iff.parseCMAP(data) → [{r,g,b}, ...]

Parse a color palette.

iff.parseILBM(tree) → {width, height, numPlanes, colors, pixels, bmhd}

Decode an ILBM all the way to chunky pixel indices. Handles ByteRun1 RLE decompression. Slow in pure JS for large images.

iff.parse8SVX(tree) → {samplesPerSec, numOctaves, name, samples, length, ...}
iff.unpackByteRun1(data, unpackedSize)

Low-level access to the RLE decompression routine.

child_process

var cp = require('child_process');
var out = cp.execSync('version');
cp.execSync(command) → string

Runs an AmigaOS command via SystemTagList, captures stdout via T:nodeamiga_exec_tmp, returns as a string.

cp.exec(command, callback?)

Same as execSync with callback(null, stdout, stderr). stderr is always an empty string — capturing it reliably on AmigaOS is non-trivial.

gui — GadTools widget toolkit

var gui = require('gui');
var win = gui.createWindow({ title: 'Demo', width: 300, height: 150,
    gadgets: [{ kind: 'button', id: 1, label: 'Click me',
                left: 10, top: 10, width: 100, height: 14 }]});
while (true) {
    var evt = gui.waitEvent(win);
    if (evt.type === 'close') break;
    if (evt.type === 'gadgetup' && evt.id === 1) console.log('clicked');
}
gui.closeWindow(win);

High-level GUI using gadtools.library. Handles layout, resizing, events, menus.

Windows

gui.createWindow({title, width, height, left, top, resizable, minWidth, minHeight, font, gadgets})

Create a window. gadgets is an array — see below. Returns a window handle (opaque object).

font may be {name, size}, e.g. {name:'topaz.font', size:8}, to force a fixed-width font (useful for columnar listviews).

gui.closeWindow(win)
gui.waitEvent(win) → event

Blocks until an event arrives. Returns {type, id?, code?, x?, y?, key?, width?, height?}.

gui.pollEvent(win) → event | null

Non-blocking variant.

gui.setTitle(win, title)
gui.setMenu(win, menus)

Install a menu bar. Each entry: {title, items: [{label, id, key?}]}. Use '---' for a separator.

gui.setDisabled(win, gadgetId, flag)

Enable/disable a gadget.

gui.get(win, gadgetId) / gui.set(win, gadgetId, value)

Read/write the value of a gadget (string, number, checkbox state, listview items, etc.).

Requesters

gui.fileRequest({title, pattern?, drawer?, file?, save?}) → {path, file, drawer} | null

ASL file requester.

gui.fontRequest({title}) → {name, size, style} | null
gui.screenInfo() → {fontName, fontWidth, fontHeight, screenWidth, screenHeight, borderLeft, borderRight, borderTop, borderBottom}

Gadget kinds

Pass these in gadgets: array when creating a window. Each has id, left, top, width, height (pixels or 'NN%' strings for layouts relative to the window; negative values anchor from the opposite edge).

kindPurposeEvents
buttonPush button with labelgadgetup
stringText entry, value initialgadgetup on Enter
textRead-only text, value
integerNumeric entry, valuegadgetup
checkboxBoolean, value: 0/1gadgetup with code=0/1
cycleDropdown, items: [...], value indexgadgetup with code=index
mxRadio-button group, items, value indexgadgetdown with code=index
sliderHorizontal slider, min, max, valuegadgetup/mousemove
scrollerVertical scroller, max, value, visiblegadgetup with code=top
listviewScrollable list, items: [...], value selected indexgadgetup with code=index
numberRead-only numeric display, value
areaClickable bevel box (custom drawing)gadgetdown/gadgetup/mousemove with evt.x, evt.y

Set flex: true on a gadget to make it expand vertically to fill available space (for a listview that grows with the window).

Drawing (gui.gfx)

For custom drawing on a gui window's RastPort:

gui.gfx.setColor, setBColor, setDrawMode (0=JAM1, 1=JAM2, 2=COMPLEMENT/XOR, 4=INVERSVID), moveTo, lineTo, drawLine, drawRect, fillRect, drawCircle, fillCircle, drawEllipse, drawText, setPixel, getPixel, clear, waitTOF (vsync), innerSize, setFont.

intuition — low-level windows

var ui = require('intuition');
var win = ui.openWindow({ title: 'Raw', width: 320, height: 200 });
while (true) {
    var evt = win.waitEvent();
    if (evt.type === 'close') break;
}
win.close();

Low-level wrapper over intuition.library for plain Intuition windows — no GadTools widgets, just a blank surface you can draw on. Use this when gui is too heavy or when you want total control (games, demos, custom toolkits).

ui.openWindow({title, width, height, left, top}) → win

width/height are the inner (drawable) dimensions. Returns a window handle with methods close(), waitEvent(), pollEvent(), plus properties width, height, innerWidth, innerHeight.

Events: close, mousedown, mouseup, mousemove, keypress (with code and key), resize (when window is resized), refresh.

ui.screenInfo() → {width, height, depth}

Size of the active public screen (usually Workbench).

ui.alert(text) / ui.confirm(text) → boolean

Simple modal requesters via EasyRequestArgs.

Graphics (ui.gfx)

Same API surface as gui.gfx. Examples: ui.gfx.setColor(win, 1), ui.gfx.drawLine(win, 10,10, 100,50), etc.

clipboard

var clip = require('clipboard');
clip.write('hello');
var text = clip.read();
clip.clear();

Read/write the standard AmigaOS clipboard unit 0. Uses iffparse.library to read/write FTXT/CHRS chunks — compatible with all standard Amiga text editors.

clip.read() → string

Returns "" if the clipboard is empty or contains no text. Reads up to 1 MB per chunk.

clip.write(text) → boolean

Returns true on success.

clip.clear()

Empties the clipboard (writes an empty FTXT).

arexx

var arexx = require('arexx');
var r = arexx.send('EDITOR', 'REDRAW');
console.log(r.rc, r.result);

Communicate with ARexx-aware AmigaOS applications via message ports.

arexx.send(portName, command) → {rc, result}

Send a command to a port and wait for the reply. rc is the ARexx return code (0 on success, non-zero on error). result is the string result, or an error description if the port wasn't found.

arexx.createPort(name) → port

Create a named port that other applications can send commands to.

arexx.closePort(port)
arexx.getMsg(port) → {command, _msg} | null

Non-blocking; returns null if no message is waiting.

arexx.waitMsg(port) → {command, _msg}

Blocks until a message arrives.

arexx.reply(msg, rc, result)

Reply to a received message.

arexx.listPorts() → [name, ...]

Returns the names of all public ports in the system.

amiga — FFI (call any library)

var amiga = require('amiga');
var intBase = amiga.openLibrary('intuition.library', 37);
var version = amiga.peek16(intBase, 20);  // lib_Version
amiga.closeLibrary(intBase);

Escape hatch for calling AmigaOS libraries directly from JavaScript. Useful when a feature you need isn't wrapped in a higher-level NodeAmiga module.

Libraries

amiga.openLibrary(name, version?) → base

Returns the library base pointer as a number, or 0 on failure.

amiga.closeLibrary(base)
amiga.execBase() → SysBase pointer

Memory

amiga.allocMem(size, flags?) → address

Default flags: MEMF_PUBLIC|MEMF_CLEAR. Allocations are tracked and freed automatically on exit if you forget.

amiga.freeMem(address, size)
amiga.peek8/16/32(address, offset?)

Read an unsigned byte/word/long.

amiga.poke8/16/32(address, offset, value)
amiga.peekString(address, offset?, maxLen?)

Read a null-terminated string (default max 4096 bytes).

amiga.pokeString(address, offset, str)

No bounds check! You are responsible for making sure str fits. Allocate enough with allocMem first.

amiga.makeString(str) → address

Allocate an AmigaOS-owned buffer and copy the string in. Tracked for auto-cleanup.

amiga.makeTags([tag1, val1, tag2, val2, ...]) → address

Allocate a TagItem array. Terminate your list with TAG_DONE (value 0) or the last pair; makeTags handles the terminator automatically.

Function calls

amiga.call(base, offset, regs) → d0

Call a library function at the given LVO offset (negative, e.g. -216 for exec AvailMem). regs is an object like {d0: ..., d1: ..., a0: ...}. Returns the value in d0 as a number.

Uses an assembly trampoline (ffi_asm.s) to load d0-d7 and a0-a5 from your object, sets a6 to base automatically, then calls the function.

// example: exec AvailMem(MEMF_CHIP) via FFI
var execLib = amiga.execBase();
var chip = amiga.call(execLib, -216, { d1: 0x02 });  // MEMF_CHIP
console.log('Chip free:', chip, 'bytes');

FFI is unsafe — by design

This module bypasses all type checking. Incorrect register values or out-of-bounds writes will crash your Amiga. Use it carefully and test on real hardware (or an emulator snapshot) before shipping.