{"id":"flipbook-labs/archivist","name":"archivist","scope":"flipbook-labs","platform":"roblox","description":"Mirrored from the Wally registry.","version":"0.2.0","latest":"0.2.0","versions":["0.1.0","0.2.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"effc6027dbc9839caeee190550a1373d96de49411e8fe4de2b59e8514add89da","likes":0,"downloads":0,"install":"forest install flipbook-labs/archivist","url":"https://forest.dev/p/roblox/flipbook-labs/archivist","files":"https://api.forest.dev/ai/package/roblox/flipbook-labs/archivist/files","readme":"# Archivist\n\nA structured logging library for Luau that runs on both [Lute](https://github.com/luau-lang/lute) and Roblox.\n\n> [!NOTE]\n> Archivist is pre-release and under active development. The API may change before v1.\n\n## Features\n\n- **Dual runtime**: one library, first-class support for Lute (CLI) and Roblox\n- **Log levels**: `trace`, `debug`, `info`, `warn`, `err`, filtered by a minimum level\n- **`LOG_LEVEL`**: level resolution from the environment on Lute, `_G.LOG_LEVEL` on Roblox\n- **Colorful output**: ANSI-colored console output on Lute; plain `print`/`warn` on Roblox\n- **Structured records**: every entry is a `LogRecord` object (timestamp, level, name, args) that sinks can consume\n- **Sinks**: route records anywhere: console, files (Lute), or your own callback (e.g. an in-app log viewer)\n- **Dev/prod deferral**: sequential `print`-like output in dev; in prod, records batch and each sink is written once per batch instead of once per record\n\n## Installation\n\n### Lute (Loom)\n\nAdd to your `loom.config.luau` dependencies:\n\n```luau\nArchivist = {\n\trev = \"v0.1.0\",\n\tsourceKind = \"github\",\n\tsource = \"https://github.com/flipbook-labs/archivist\",\n},\n```\n\nThen run `lute pkg install`.\n\n### Roblox (Wally)\n\n```toml\n[dependencies]\nArchivist = \"flipbook-labs/archivist@0.1.0\"\n```\n\n## Usage\n\n```luau\nlocal Archivist = require(\"@pkg/Archivist\")\n\nlocal logger = Archivist.createLogger(\"MyModule\")\n\nlogger.info(\"loaded\", 3, \"stories\")\nlogger.info(\"structured data:\", { port = 8080, ready = true })\nlogger.warn(\"something looks off\")\nlogger.err(\"something broke\")\n\n-- Children share the parent's sinks and attach fields to every record:\nlocal child = logger.child(\"requests\", { requestId = \"abc123\" })\nchild.debug(\"handling request\")\n\n-- Prod mode batches: these queue and flush to each sink as ONE write.\nlocal batched = Archivist.createLogger(\"Telemetry\", { mode = \"Prod\" })\nbatched.info(\"queued 1\")\nbatched.info(\"queued 2\")\nbatched.flush() -- optional; pending batches also flush on defer and at exit\n\n-- Show everything, regardless of LOG_LEVEL:\nlocal verbose = Archivist.createLogger(\"MyModule\", { level = \"Trace\" })\n```\n\n### Pretty output middleware\n\nThe default console formatter emits the level and message:\n\n```text\n[info] loaded 3 stories\n```\n\nAdd the built-in middleware when you want logger names or timestamps:\n\n```luau\nlocal logger = Archivist.createLogger(\"MyModule\", {\n\tmiddleware = {\n\t\tArchivist.middleware.name,\n\t\tArchivist.middleware.timestamp,\n\t},\n})\n```\n\nMiddleware runs in declaration order. Each function receives the formatted line and a context containing the structured record, platform, color setting, and a color-aware `style` helper. It can prepend, append, or replace text.\n\nThe logger-level `middleware` option configures its default console sink. When you provide `sinks`, pass middleware to the pretty formatter instead:\n\n```luau\nlocal formatter = Archivist.createPrettyFormatter({\n\tmiddleware = {\n\t\tArchivist.middleware.name,\n\t},\n})\nlocal logger = Archivist.createLogger(\"MyModule\", {\n\tsinks = {\n\t\tArchivist.createConsoleSink({ formatter = formatter }),\n\t},\n})\n```\n\n### Sinks\n\n```luau\nlocal logger = Archivist.createLogger(\"App\", {\n\tsinks = {\n\t\t-- The runtime's console: colored stdout on Lute, print/warn on Roblox.\n\t\tArchivist.createConsoleSink(),\n\n\t\t-- Any custom destination, e.g. an in-app log viewer panel:\n\t\tArchivist.createCallbackSink(function(record)\n\t\t\tLogsStore.addLine(record)\n\t\tend),\n\n\t\t-- A JSON-lines log file (Lute only):\n\t\tArchivist.createFileSink({ path = \"logs/app.log\" }),\n\n\t\t-- Ship batches to an external platform; bring your own HTTP client:\n\t\tArchivist.createTransportSink({\n\t\t\tbatchSize = 50,\n\t\t\tsend = function(records)\n\t\t\t\thttpClient.post(INGEST_URL, records)\n\t\t\tend,\n\t\t}),\n\t},\n})\n```\n\nFormatters control how text-oriented sinks render records: `createPrettyFormatter` (human-readable, optional ANSI color and middleware) and `createJsonFormatter` (one JSON object per line). Sinks that consume records structurally (`createCallbackSink`, `createTransportSink`) bypass formatting entirely.\n\nThe minimum level resolves from, in order: the `level` option, the `LOG_LEVEL`\nenvironment variable (Lute), `_G.LOG_LEVEL` (Roblox), then defaults to `info`.\n\n`Archivist.getLogger(name)` returns a per-name cached logger so modules can\nshare one configured logger without threading it through requires.\n\n## Development\n\nArchivist uses [Rokit](https://github.com/rojo-rbx/rokit) for toolchain management.\n\n```sh\nrokit install\nlute run example   # run the demo script under Lute\nlute test          # run the unit tests\nlute run build     # build the Roblox model (Archivist.rbxm)\n```\n\n## License\n\n[MIT](LICENSE)\n","readmeTruncated":false}