sqlc plugin for MoonBit
Dependencies
⚠️ Experimental: This project is experimental and under active development. APIs may change without notice.
| Backend | Target | Runtime | Dependencies |
|---|---|---|---|
| sqlite | native | Native binary | mizchi/sqlite |
| sqlite_js | js | Node.js / Browser | mizchi/sqlite, mizchi/js |
| d1 | js | Cloudflare Workers | mizchi/cloudflare, mizchi/js |
| postgres | native | Native binary | moonbit-community/postgres |
| postgres_js | js | Node.js | mizchi/npm_typed/pg, mizchi/js |
| mysql_js | js | Node.js | mizchi/js (mysql2 npm package) |
version: "2"
plugins:
- name: moonbit
wasm:
url: "https://github.com/mizchi/sqlc_gen_moonbit/releases/download/v0.4.0/sqlc-gen-moonbit.wasm"
sha256: "8639024dc5ee7271e1b4a8dfec853e85a72814577d66f30810b64270f7fead05"
sql:
- engine: sqlite
schema: "schema.sql"
queries: "query.sql"
codegen:
- plugin: moonbit
out: "gen"
options:
backend: "sqlite" # or "d1" for Cloudflare D1moon update
moon build --target wasm ./cmd/wasm
# Output: target/wasm/release/build/cmd/wasm/wasm.wasmplugins:
- name: moonbit
wasm:
url: "file://./path/to/wasm.wasm"
sha256: "" # Optional for local filesCREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE
);-- name: GetUser :one
SELECT * FROM users WHERE id = ?;
-- name: ListUsers :many
SELECT * FROM users ORDER BY name;
-- name: CreateUser :exec
INSERT INTO users (name, email) VALUES (?, ?);sqlc generate{
"deps": {
"mizchi/sqlite": "0.1.3",
"moonbitlang/x": "0.4.40"
}
}fn main {
let db = @sqlite.sqlite_open_v2(...)
// Create user
@gen.create_user(db, @gen.CreateUserParams::new("Alice", "alice@example.com"))
// List users
let users = @gen.list_users(db)
// Get user by ID
match @gen.get_user(db, @gen.GetUserParams::new(1L)) {
Some(user) => println("Found: " + user.name)
None => println("Not found")
}
}{
"deps": {
"mizchi/cloudflare": "0.1.6",
"mizchi/js": "0.10.10",
"moonbitlang/async": "0.16.0"
}
}///|
pub async fn handler(
db : @cloudflare.D1Database,
) -> Unit raise @cloudflare.D1Error {
// Create user
@gen.create_user(db, @gen.CreateUserParams::new("Alice", "alice@example.com"))
// List users (async)
let users = @gen.list_users(db)
// Get user by ID (async)
match @gen.get_user(db, @gen.GetUserParams::new(1L)) {
Some(user) => println("Found: " + user.name)
None => println("Not found")
}
}{
"deps": {
"mizchi/npm_typed": "0.1.2",
"mizchi/js": "0.10.10",
"moonbitlang/x": "0.4.40"
}
}npm install pg///|
async fn run_tests_inner() -> Unit {
let pool = @pg.Pool::new(
host="localhost",
port=5432,
user="postgres",
password="postgres",
database="mydb",
)
// Create user (async, returns inserted id)
let user_id = @gen.create_user(
pool,
@gen.CreateUserParams::new("Alice", "alice@example.com"),
)
// List users (async)
let users = @gen.list_users(pool)
// Get user by ID (async)
match @gen.get_user(pool, @gen.GetUserParams::new(user_id)) {
Some(user) => println("Found: \{user.name}")
None => println("Not found")
}
pool.end()
}
///|
async fn run_tests() -> Unit noraise {
run_tests_inner() catch {
e => println("Error: \{e}")
}
}
///|
fn main {
@core.run_async(run_tests)
}| Option | Type | Default | Description |
|---|---|---|---|
| backend | "sqlite" | "sqlite_js" | "d1" | "postgres" | "postgres_js" | "mysql_js" | "sqlite" | Target backend |
| validators | bool | false | Generate validation functions |
| json_schema | bool | false | Generate JSON Schema |
| overrides | array | [] | Custom type mappings |
codegen:
- plugin: moonbit
out: "db/gen"
options:
backend: "d1"
validators: true
json_schema: true
overrides:
- column: "users.id"
moonbit_type: "UserId"
- db_type: "uuid"
moonbit_type: "@mypackage.UUID"| Field | Type | Description |
|---|---|---|
| column | string | Column name in table.column format |
| db_type | string | Database type (e.g., INTEGER, TEXT) |
| moonbit_type | string | MoonBit type (supports package paths like @pkg.Type) |
| Annotation | Return Type | Description |
|---|---|---|
| :one | T? | Returns single row or None |
| :many | Array[T] | Returns all matching rows |
| :exec | Unit | Executes without returning data |
| :execrows | Int | Returns number of affected rows |
| :execlastid | Int64 | Returns last inserted ID (for INSERT ... RETURNING id) |
assert.deepEqual(call.params, ["mizchi", 100, 0]);# Clone and build
git clone https://github.com/mizchi/sqlc_gen_moonbit
cd sqlc_gen_moonbit
# Show help
moon run tools/codegen --target native -- --help
# Generate code (stdout)
moon run tools/codegen --target native -- queries.sql
# Generate to file with D1 backend
moon run tools/codegen --target native -- -b d1 -o db/gen/sqlc_queries.mbt queries.sql
# Check dependencies
moon run tools/codegen --target native -- --check-deps -b d1 queries.sql| Option | Description |
|---|---|
| -o, --output <file> | Output file (default: stdout) |
| -c, --config <file> | Config file (JSON) |
| -b, --backend <type> | Backend: sqlite, sqlite_js, d1, postgres, postgres_js, mysql_js |
| --validators | Generate validation functions |
| --json-schema | Generate JSON schema |
| --check-deps | Check required dependencies in moon.mod.json |
{
"backend": "sqlite",
"validators": true,
"json_schema": false,
"overrides": [
{ "column": "users.id", "moonbit_type": "UserId" },
{ "db_type": "uuid", "moonbit_type": "@uuid.UUID" }
]
}-- @query GetUser :one
-- @param id INTEGER
-- @returns id INTEGER, name TEXT, email TEXT
SELECT * FROM users WHERE id = ?;
-- @query ListUsers :many
-- @returns id INTEGER, name TEXT, email TEXT
SELECT * FROM users ORDER BY name;
-- @query CreateUser :exec
-- @param name TEXT
-- @param email TEXT
INSERT INTO users (name, email) VALUES (?, ?);moon add mizchi/sqlc_gen_moonbit///|
fn main {
let sql_content = @fs.read_file_to_string("queries.sql") catch {
e => panic()
}
let code = @codegen.generate_from_sql(sql_content)
println(code)
}import {
"moonbitlang/x/fs",
"mizchi/sqlc_gen_moonbit/lib/codegen",
}
options(
"is-main": true,
)moon run tasks > db/gen/sqlc_queries.mbt// 1. Sqlc-generated query lives in the `@db` package.
///|
async fn list_pages_markdown(
binding : String,
handle : String,
limit : Int,
offset : Int,
) -> String raise Error {
let db = d1_binding(binding)
let params = @db.ListPagesParams::new(
handle,
limit.to_int64(),
offset.to_int64(),
)
let rows = @db.list_pages(db, params)
let rows_json = serialise_rows(rows) // builds Json::array(...).stringify()
// 2. JS renderer takes the JSON, no DB access here.
render_pages_markdown(rows_json, handle)
}
///|
extern "js" fn render_pages_markdown(
rows_json : String,
handle : String,
) -> String =
#| (rowsJson, handle) => {
#| const rows = JSON.parse(rowsJson);
#| // ...pure string building (escape, sort, format)...
#| return out;
#| }Install
Download zipsqlc plugin for MoonBit
Dependencies