moonbit_sqlc_plugin

sqlc WASM plugin ? generate type-safe MoonBit database layer from SQL queries

sqlc
codegen
database
wasm-plugin
moon add Mairzzcllo/moonbit_sqlc_plugin@0.1.9
Download zip
Version
0.1.9
License
Apache-2.0
Last updated
last month
Downloads
57
README

#MoonBit sqlc WASM Plugin

#Description

MoonBit sqlc WASM Plugin is a sqlc WASM code generator for MoonBit. It reads schema.sql and query.sql, validates SQL and types at compile time, and emits type-safe MoonBit source (types.mbt + queries.mbt).

Generated functions take DB or Transaction directly — no ORM, no reflection. The runtime is published on mooncakes.io; the WASM plugin is built locally or downloaded from GitHub Releases.

Current scope: PostgreSQL · sqlc v1.27+ (tested v1.31.1) · MoonBit WASM (WASI preview1)

#Key Features

#Type-Safe Codegen

  • Result[T, DBError] for all query and decode paths
  • Compile-time SQL/type validation via sqlc
  • AST → Pretty Printer pipeline (no string concatenation)

#Minimal Runtime

  • DB, Transaction, Row, RowIter, Value, MockDB
  • Published as Mairzzcllo/moonbit_sqlc_plugin/runtime on mooncakes 0.1.8
  • Target wasm-gc — no native driver required in generated code

#Plugin-Host Separation

  • WASM plugin handles codegen only
  • WASI stdin/stdout protobuf I/O (inline WAT FFI, no external shim)
  • Dual-file output: types.mbt + queries.mbt

#Quick Start

Two paths — pick the one that matches your role:

PathAudienceWhat you need
A — mooncakes.ioUse generated types.mbt / queries.mbt in your appMoonBit + moon add (no plugin repo clone)
B — Plugin repoBuild WASM plugin, run examples, contributeMoonBit + sqlc + this repository


#A. App Developers — mooncakes.io

Generated code references runtime via @runtime.* (declare the alias in moon.pkg). Install runtime from the MoonBit package registry — the WASM plugin itself is not on mooncakes.

ItemValue
PackageMairzzcllo/moonbit_sqlc_plugin
Version0.1.8
Import pathMairzzcllo/moonbit_sqlc_plugin/runtime
Docshttps://mooncakes.io/docs/Mairzzcllo/moonbit_sqlc_plugin
Targetwasm-gc (do not use native)

#Add runtime to an existing project

In your MoonBit project root (moon.mod.json already exists):

moon update moon add Mairzzcllo/moonbit_sqlc_plugin@0.1.8 moon check --target wasm-gc

moon add writes into moon.mod.json:

{ "deps": { "Mairzzcllo/moonbit_sqlc_plugin": "0.1.8" } }

Add to the package moon.pkg that holds generated code:

import { "Mairzzcllo/moonbit_sqlc_plugin/runtime" @runtime, }

Generated types.mbt / queries.mbt use @runtime.* for runtime types and do not emit package or source-level import.

Copy types.mbt + queries.mbt from sqlc generate, then verify:

moon check --target wasm-gc moon test --target wasm-gc

moon add pulls from mooncakes.io and does not require login. Only moon publish needs credentials.

#Minimal new project (from scratch)

mkdir myapp && cd myapp

moon.mod.json:

{ "name": "your_org/myapp", "version": "0.1.0", "preferred-target": "wasm-gc", "supported-targets": "+wasm+wasm-gc" }

moon.pkg:

import { "Mairzzcllo/moonbit_sqlc_plugin/runtime" @runtime, }

Then:

moon update moon add Mairzzcllo/moonbit_sqlc_plugin@0.1.8 # copy types.mbt + queries.mbt here moon check --target wasm-gc

#Upgrade / remove

moon add Mairzzcllo/moonbit_sqlc_plugin@0.1.8 # upgrade moon remove Mairzzcllo/moonbit_sqlc_plugin # remove

Smoke test (run from this plugin repo root):

.\scripts\setup-mooncakes.ps1 -Version 0.1.8

bash scripts/setup-mooncakes.sh --version 0.1.8


#B. Plugin Developers — Build WASM & Generate Code

#Requirements

ToolVersionNotes
MoonBit≥ 0.1.20260522Build, test, mooncakes
sqlc≥ v1.27.0Invokes WASM plugin

PostgreSQL is only used by sqlc to validate schema/query files. Generated code does not connect to a database.

#Clone Repository

git clone https://github.com/Mairzzcllo/MoonBit-sqlc-WASM-plugin.git cd MoonBit-sqlc-WASM-plugin moon check moon test

#Build WASM Plugin

moon build --target wasm --release

ModePath
release (recommended)_build/wasm/release/build/plugin/plugin.wasm
debug_build/wasm/debug/build/plugin/plugin.wasm

#Run Example

#Linux / macOS

chmod +x scripts/run-example.sh scripts/setup-mooncakes.sh bash scripts/run-example.sh bash scripts/run-example.sh --full --release --skip-build

#Windows (PowerShell)

.\scripts\run-example.ps1 .\scripts\run-example.ps1 -Full -Release -SkipBuild $OutputEncoding = [Console]::OutputEncoding = [Text.Encoding]::UTF8

Output: examples/users/types.mbt and examples/users/queries.mbt.

#Configure sqlc.yaml and Generate

version: "2" plugins: - name: moonbit wasm: url: file://./_build/wasm/release/build/plugin/plugin.wasm sha256: "" sql: - engine: postgresql schema: schema.sql queries: query.sql codegen: - out: gen plugin: moonbit options: package_name: myapp

sqlc generate

Note: Do not commit platform-specific sha256 hashes. Use scripts/sync-sqlc-sha256.ps1 after building locally.

After sqlc generate, link runtime via Path A (moon add from mooncakes.io).

#Usage Example

fn example(db: @runtime.DB) {
match query_get_user(db, 42L) {
Ok(user) => println(user.name)
Err(@runtime.DBError::NoRows) => println("not found")
Err(e) => println("error: \{e}")
}
}

Declare @runtime in moon.pkg. Construct @runtime.DB in your driver adapter; use @runtime.MockDB in tests.

#Plugin Options

OptionDefaultDescription
package_name"main"Legacy option (parsed, not emitted since 0.1.7)
emit_sql_as_commenttrueEmbed SQL above each function
emit_json_tagsfalseEmit @json.tag(...)
emit_empty_slicesfalseReturn [] for empty :many results
emit_exact_table_namesfalseSingularize table names (usersUser)
emit_methods_with_db_argumentfalsesqlc compat; always emits standalone query_* fns

#Troubleshooting

SymptomFix
moonbit_simd.h missingUse --target wasm-gc, not native
moon add package not foundRun moon update first to refresh registry index
Generated code missing DB / RowAdd runtime import in moon.pkg
WASM path not foundUse _build/wasm/..., not target/
sha256 mismatchDo not commit local hashes; run scripts/sync-sqlc-sha256.ps1
Windows garbled output$OutputEncoding = [Console]::OutputEncoding = [Text.Encoding]::UTF8
sqlc cannot find pluginBuild WASM first; verify file:// path matches build mode

#Project Structure

plugin/ # WASM plugin (codegen + WASI I/O) runtime/ # Generated-code runtime (published on mooncakes) examples/users/ # Reproducible example tests/ # golden + integration tests docs/ # API reference and quickstart scripts/ # run-example / setup-mooncakes / sync-sqlc-sha256

#Tests

moon check --deny-warn moon test --deny-warn # 937 inline tests moon build --target wasm --release

tests/integration/wasm/validate_plugin.ps1 -TestSqlc -Release -SkipBuild tests/integration/e2e/run_e2e.ps1 -SkipBuild -Release

#Architecture

sqlc (protobuf) → wasi_io → codec → adapter → ir → type_codegen / query_codegen → ast → emitter → types.mbt + queries.mbt

I/O uses inline WAT FFI for WASI fd_read / fd_write (no external shim). Protocol based on sqlc-gen-greeter (MIT).

#Docs and Links

#LICENSE

This project is licensed under the Apache License 2.0 — see LICENSE.

Third-party notices are in NOTICE. WASM I/O protocol reference: sqlc-gen-greeter (MIT).