A CLI tool that generates a Lua client library from an OpenAPI spec.
Most of this project was vibe coded. Please review the output and use at your own risk.
Given an OpenAPI (v3) JSON file, this tool generates a Lua module with a nested table structure that mirrors your API paths, and convenience methods for each operation.
I couldn’t find a working generator that fit my needs, and I only needed this for a specific use case. If a better tool comes around, I’ll likely just archive this one.
- Node.js
- npm
npx openapi-2-lua --spec openapi.json --out client.lua --name Clientnpm i -g openapi-2-lua
openapi-2-lua --spec openapi.json --out client.lua --name Clientnpx openapi-2-lua@latests --spec openapi.json --out client.lua --name Client-s, --spec <file>: Path to the OpenAPI spec file (default:openapi.json)-o, --out <file>: Output Lua file path (default:client.lua)-n, --name <clientName>: Lua client table name (default:Client)
The generated client expects you to provide a request function on construction that accepts a single table argument in this shape:
-- request { url = string, body? = string, headers? = { [string] = string }, binary? = boolean,
-- method? = string, redirect? = boolean, timeout? = number }The generated client calls it like:
return self.request(request_options)request_options: { url = self.baseUrl .. options.url, body = options.body, headers = options.headers, binary = options.binary, method = options.method, redirect = options.redirect, timeout = options.timeout}
Pass query parameters via options.query on any generated endpoint call.
client.echo.post({
query = {
q = "hello world",
count = 2,
include = { "a", "b" }
}
})
-- /echo?count=2&include=a&include=b&q=hello%20worldNotes:
- Query keys are sorted for deterministic ordering.
- Values are URL-encoded.
- Array values emit repeated keys (
include=a&include=b).
local Client = require("client")
local client = Client:new({
baseUrl = "https://api.example.com",
request = function(opts)
-- implement your HTTP call here
-- opts.url, opts.method, opts.headers, opts.body, ...
end
})
-- Example endpoint call (depends on your spec)
-- client.users["@me"].get()- Path segments that aren’t valid Lua identifiers (e.g.
@me) are emitted using bracket access (e.g.users["@me"]). - Path parameters become function arguments (e.g.
/users/{target}/flags->get(target, options)).
This repo includes a GitHub Actions workflow that publishes to npm when you push a version tag like v1.2.3.
- Required repo secret:
NPM_TOKEN - Workflow:
.github/workflows/publish-npm.yml