MoonBit bindings for Cloudflare Workers APIs (KV, D1, R2, Durable Objects, etc.)
Dependencies
{
"deps": {
"mizchi/js": "0.8.2",
"mizchi/cloudflare": "0.1.0"
}
}# Install dependencies
pnpm install
# Run development server
pnpm dev
# Run tests
pnpm test| Service | Package | Status | Note |
|---|---|---|---|
| Core Platform | |||
| Workers Runtime | mizchi/js/cloudflare | 🧪 Tested | Basic runtime bindings |
| Environment Context | mizchi/js/cloudflare | 🧪 Tested | Env/ExecutionContext |
| Storage Services | |||
| KV (Key-Value) | mizchi/js/cloudflare | 🧪 Tested | Get/Put/Delete/List |
| D1 (SQL Database) | mizchi/js/cloudflare | 🧪 Tested | Queries/Prepared/Batch |
| R2 (Object Storage) | mizchi/js/cloudflare | 🧪 Tested | Objects/Multipart/Metadata |
| Durable Objects | mizchi/js/cloudflare | 🧪 Tested | Storage/Alarms/State |
| Compute & Network | |||
| Workers AI | mizchi/cloudflare, mizchi/cloudflare/ai | 🧪 Tested | AI binding + AI SDK wrapper |
| Vectorize | mizchi/cloudflare | 🧪 Tested | Vector index operations |
| Queues | mizchi/cloudflare | 🧪 Tested | Producer + consumer batch APIs |
| Workers Analytics Engine | mizchi/cloudflare | 🧪 Tested | writeDataPoint |
| Hyperdrive | mizchi/cloudflare | 🧪 Tested | Connect + connection metadata |
| Email Workers | mizchi/cloudflare | 🧪 Tested | Send/forward/reply APIs |
| Browser Rendering | mizchi/cloudflare | 🧪 Tested | Fetcher/connect bindings |
| Security & Auth | |||
| Access | mizchi/cloudflare | 🧪 Tested | Access header + TLS auth helpers |
| Turnstile | mizchi/cloudflare | 🧪 Tested | Siteverify helper |
{
"import": [
"mizchi/js",
"mizchi/js/web/url",
"mizchi/js/web/http",
"mizchi/js/web/worker",
"mizchi/js/cloudflare"
]
}// Get a value
let value = kv.get("my-key").await()
// Put a value
kv.put("my-key", "my-value").await()
// Delete a value
kv.delete("my-key").await()
// List keys
let result = kv.list().await()// Get with options
let value = kv.get(
"my-key",
type_?=Some("json"),
cacheTtl?=Some(60)
).await()
// Get as JSON
let json_data = kv.get_json("my-data").await()
// Put with metadata and TTL
kv.put(
"my-key",
"my-value",
expirationTtl?=Some(3600),
metadata?=Some(js({"version": 1}))
).await()
// List with filtering
let result = kv.list(
prefix?=Some("user:"),
limit?=Some(100)
).await()// Prepare and execute a query
let stmt = db.prepare("SELECT * FROM users WHERE id = ?")
let result = stmt.bind1(js(1)).all().await()
// Direct execution
let result = db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)").await()
// Batch operations
let stmts = [
db.prepare("INSERT INTO users VALUES (?, ?)").bind2(js(1), js("Alice")),
db.prepare("INSERT INTO users VALUES (?, ?)").bind2(js(2), js("Bob"))
]
let results = db.batch(stmts).await()// Get first row
let first = stmt.first().unwrap()
// Get specific column from first row
let name = stmt.first_col("name").await()
// Get all rows
let result = stmt.all().unwrap()
let rows = result.get_results()
// Raw results as arrays
let raw = stmt.raw().unwrap()// Put an object
let obj = bucket.put("file.txt", js("Hello, World!")).await()
// Get an object
let obj = bucket.get("file.txt").await()
match obj {
Some(o) => {
let text = o.text().await()
// Use text...
}
None => ()
}
// Delete an object
bucket.delete("file.txt").await()
// List objects
let objects = bucket.list().await()// Put with metadata
let http_meta = R2HttpMetadata::{
contentType: Some("text/plain"),
contentLanguage: Some("en"),
cacheControl: Some("max-age=3600"),
contentDisposition: None,
contentEncoding: None,
cacheExpiry: None
}
bucket.put(
"file.txt",
js("content"),
httpMetadata?=Some(http_meta),
customMetadata?=Some(js({"author": "Alice"}))
).await()
// Conditional get
let cond = R2Conditional::{
etagMatches: Some("abc123"),
etagDoesNotMatch: None,
uploadedBefore: None,
uploadedAfter: None
}
let obj = bucket.get(
"file.txt",
onlyIf?=Some(cond)
).await()
// List with filtering
let result = bucket.list(
limit?=Some(1000),
prefix?=Some("images/"),
delimiter?=Some("/"),
include_?=Some(["httpMetadata", "customMetadata"])
).await()
// Multipart upload
let upload = bucket.create_multipart_upload("large-file.bin").await()
let part1 = upload.upload_part(1, js(data1)).await()
let part2 = upload.upload_part(2, js(data2)).await()
let obj = upload.complete([part1, part2]).await()// Get by name (deterministic ID)
let stub = namespace.get_by_name("my-object")
// Get by unique ID
let id = namespace.new_unique_id()
let stub = namespace.get(id)
// Get with jurisdiction
let id = namespace.new_unique_id(jurisdiction?=Some("eu"))// Fetch request
let response = stub.fetch_url("/api/endpoint").await()
// Fetch with init options
let init = js({"method": "POST", "body": "data"})
let response = stub.fetch_url_with_init("/api/endpoint", init).await()// Access storage
let storage = state.storage()
// Get/Put/Delete
let value = storage.get("counter").await()
storage.put("counter", js(42)).await()
storage.delete("key").await()
// List keys
let entries = storage.list(
prefix?=Some("user:"),
limit?=Some(100)
).await()
// Transactions
let closure = js(/* transaction function */)
let result = storage.transaction(closure).await()
// Alarms
storage.set_alarm(timestamp).await()
let alarm_time = storage.get_alarm().await()
storage.delete_alarm().await()
// Wait until
state.wait_until(promise)
// Block concurrency
let callback = js(/* async function */)
state.block_concurrency_while(callback).await()// Get with options
let value = storage.get(
"key",
allowConcurrency?=Some(true),
noCache?=Some(false)
).await()
// Put with options
storage.put(
"key",
js(value),
allowConcurrency?=Some(true),
allowUnconfirmed?=Some(false),
noCache?=Some(false)
).await()// Convert to Val
let num = js(42)
let str = js("hello")
let bool = js(true)
let obj = js({"key": "value"})
// Cast from Val
let number : Int = val.cast()
let text : String = val.cast()// With error handling
let result = try {
let value = kv.get("key", None).await()
Ok(value)
} catch {
e => Err(e)
}# Run all tests
pnpm test
# Run only Cloudflare tests
pnpm test:cloudflare
# Watch mode
pnpm test:watch
pnpm test:cloudflare:watchimport { env } from 'cloudflare:test';
import { describe, it, expect } from 'vitest';
describe('My Feature', () => {
it('should work correctly', async () => {
const kv = env.TEST_KV as KVNamespace;
await kv.put('key', 'value');
const result = await kv.get('key');
expect(result).toBe('value');
});
});type CloudflareFetchHandler = (CloudflareRequest, CloudflareEnv, CloudflareContext) -> Promise[Response]pub suberror D1Error {
D1Error(String)
}#external
pub type AI#external
pub type AlarmInfo#external
pub type AnalyticsEngineDatasetfn AnalyticsEngineDataset::write_data_point(self : AnalyticsEngineDataset, event? : AnalyticsEngineDataPoint) -> Unit#external
pub type BrowserFetcherasync fn BrowserFetcher::fetch_request(self : BrowserFetcher, request : Request, init? : Any) -> Response#external
pub type CloudflareContext#alias(pass_through_exception)
fn CloudflareContext::passThroughOnException(self : CloudflareContext) -> Unit#alias(wait_until)
fn CloudflareContext::waitUntil(self : CloudflareContext, promise : Promise[Unit]) -> Unit#external
pub type CloudflareEnvfn CloudflareEnv::get_analytics_engine_binding(self : CloudflareEnv, key : String) -> AnalyticsEngineDataset?fn CloudflareEnv::get_browser_fetcher_binding(self : CloudflareEnv, key : String) -> BrowserFetcher?fn CloudflareEnv::get_durable_object_namespace(self : CloudflareEnv, key : String) -> DurableObjectNamespace?fn CloudflareEnv::get_sandbox_namespace(self : CloudflareEnv, key : String) -> DurableObjectNamespace?pub(all) struct ContentOptions {
html : Bool
}#external
pub type D1Databaseasync fn D1Database::batch(self : D1Database, statements : Array[D1PreparedStatement]) -> Array[D1Result] raise D1Error#external
pub type D1ExecResult#external
pub type D1Meta#external
pub type D1PreparedStatementfn D1PreparedStatement::bind(self : D1PreparedStatement, params : Array[Any]) -> D1PreparedStatementfn D1PreparedStatement::bind2(self : D1PreparedStatement, p1 : Any, p2 : Any) -> D1PreparedStatementfn D1PreparedStatement::bind3(self : D1PreparedStatement, p1 : Any, p2 : Any, p3 : Any) -> D1PreparedStatementasync fn D1PreparedStatement::first_col(self : D1PreparedStatement, col_name : String) -> Any? raise D1Errorasync fn D1PreparedStatement::raw(self : D1PreparedStatement, columnNames? : Bool) -> Array[Any] raise D1Error#alias(D1ResultSet)
#external
pub type D1Result#external
pub type Doctype#external
pub type DocumentEndfn DocumentEnd::append(self : DocumentEnd, content : String, options : ContentOptions) -> DocumentEndpub(all) struct DocumentHandler {
doctype : (Doctype) -> Unit?
comments : (HTMLComment) -> Unit?
text : (TextChunk) -> Unit?
end : (DocumentEnd) -> Unit?
}pub(all) struct DurableObjectGetAlarmOptions {
allowConcurrency : Bool?
}pub(all) struct DurableObjectGetOptions {
allowConcurrency : Bool?
noCache : Bool?
}pub(all) struct DurableObjectId {
name : String?
}pub(all) struct DurableObjectIdOptions {
jurisdiction : String?
}pub(all) struct DurableObjectListOptions {
start : String?
startAfter : String?
end : String?
prefix : String?
reverse : Bool?
limit : Int?
allowConcurrency : Bool?
noCache : Bool?
}#external
pub type DurableObjectNamespacefn DurableObjectNamespace::get(self : DurableObjectNamespace, id : DurableObjectId) -> DurableObjectStubfn DurableObjectNamespace::get_by_id_string(self : DurableObjectNamespace, id : String) -> DurableObjectStubfn DurableObjectNamespace::get_by_name(self : DurableObjectNamespace, name : String) -> DurableObjectStubfn DurableObjectNamespace::id_from_name(self : DurableObjectNamespace, name : String) -> DurableObjectIdfn DurableObjectNamespace::id_from_string(self : DurableObjectNamespace, id : String) -> DurableObjectIdfn DurableObjectNamespace::new_unique_id_with_options(self : DurableObjectNamespace, options : DurableObjectIdOptions) -> DurableObjectIdpub(all) struct DurableObjectPutOptions {
allowConcurrency : Bool?
allowUnconfirmed : Bool?
noCache : Bool?
}pub(all) struct DurableObjectSetAlarmOptions {
allowConcurrency : Bool?
allowUnconfirmed : Bool?
}async fn DurableObjectState::block_concurrency_while(self : DurableObjectState, callback : Any) -> Unit#external
pub type DurableObjectStorageasync fn DurableObjectStorage::delete_alarm_with_options(self : DurableObjectStorage, options : DurableObjectSetAlarmOptions) -> Unitasync fn DurableObjectStorage::delete_all_with_options(self : DurableObjectStorage, options : DurableObjectPutOptions) -> Unitasync fn DurableObjectStorage::delete_multiple(self : DurableObjectStorage, keys : Array[String]) -> Intasync fn DurableObjectStorage::delete_multiple_with_options(self : DurableObjectStorage, keys : Array[String], options : DurableObjectPutOptions) -> Intasync fn DurableObjectStorage::delete_with_options(self : DurableObjectStorage, key : String, options : DurableObjectPutOptions) -> Boolasync fn DurableObjectStorage::get_alarm_with_options(self : DurableObjectStorage, options : DurableObjectGetAlarmOptions) -> Int?async fn DurableObjectStorage::get_multiple(self : DurableObjectStorage, keys : Array[String]) -> Anyasync fn DurableObjectStorage::get_multiple_with_options(self : DurableObjectStorage, keys : Array[String], options : DurableObjectGetOptions) -> Anyasync fn DurableObjectStorage::get_with_options(self : DurableObjectStorage, key : String, options : DurableObjectGetOptions) -> Any?async fn DurableObjectStorage::list_with_options(self : DurableObjectStorage, options : DurableObjectListOptions) -> Anyasync fn DurableObjectStorage::put_multiple_with_options(self : DurableObjectStorage, entries : Any, options : DurableObjectPutOptions) -> Unitasync fn DurableObjectStorage::put_with_options(self : DurableObjectStorage, key : String, value : Any, options : DurableObjectPutOptions) -> Unitasync fn DurableObjectStorage::set_alarm_with_options(self : DurableObjectStorage, scheduled_time : Int, options : DurableObjectSetAlarmOptions) -> Unitasync fn DurableObjectStub::fetch_url_with_init(self : DurableObjectStub, url : String, init : Any) -> Anyasync fn DurableObjectStub::fetch_with_init(self : DurableObjectStub, request : Any, init : Any) -> Any#external
pub type DurableObjectTransactionasync fn DurableObjectTransaction::delete_multiple(self : DurableObjectTransaction, keys : Array[String]) -> Intasync fn DurableObjectTransaction::get_multiple(self : DurableObjectTransaction, keys : Array[String]) -> Anyasync fn DurableObjectTransaction::list_with_options(self : DurableObjectTransaction, options : DurableObjectListOptions) -> Anyasync fn DurableObjectTransaction::put(self : DurableObjectTransaction, key : String, value : Any) -> Unitasync fn DurableObjectTransaction::put_multiple(self : DurableObjectTransaction, entries : Any) -> Unitasync fn DurableObjectTransaction::set_alarm(self : DurableObjectTransaction, scheduled_time : Int) -> Unit#external
pub type Elementfn Element::set_inner_content(self : Element, content : String, options : ContentOptions) -> Elementpub(all) struct ElementHandler {
element : (Element) -> Unit?
comments : (HTMLComment) -> Unit?
text : (TextChunk) -> Unit?
}#external
pub type EmailMessage#external
pub type EndTag#external
pub type ForwardableEmailMessageasync fn ForwardableEmailMessage::forward(self : ForwardableEmailMessage, rcpt_to : String, headers? : Headers) -> Unitasync fn ForwardableEmailMessage::reply(self : ForwardableEmailMessage, message : EmailMessage) -> Unit#external
pub type HTMLCommentfn HTMLComment::after(self : HTMLComment, content : String, options : ContentOptions) -> HTMLCommentfn HTMLComment::before(self : HTMLComment, content : String, options : ContentOptions) -> HTMLCommentfn HTMLComment::replace(self : HTMLComment, content : String, options : ContentOptions) -> HTMLComment#external
pub type HTMLRewriterfn HTMLRewriter::on(self : HTMLRewriter, selector : String, handler : ElementHandler) -> HTMLRewriter#external
pub type Hyperdrive#external
pub type InstanceStatus#external
pub type KVNamespaceasync fn KVNamespace::get(self : KVNamespace, key : String, type_? : String, cacheTtl? : Int) -> String?async fn KVNamespace::get_with_metadata(self : KVNamespace, key : String, type_? : String, cacheTtl? : Int) -> KVValueWithMetadataasync fn KVNamespace::list(self : KVNamespace, prefix? : String, limit? : Int, cursor? : String) -> KVListResultasync fn KVNamespace::put(self : KVNamespace, key : String, value : String, expiration? : Int, expirationTtl? : Int, metadata? : Any) -> Unitasync fn KVNamespace::put_with_metadata(self : KVNamespace, key : String, value : String, metadata : Any) -> Unitpub(all) struct MessageSendRequest {
body : Any
contentType : QueueContentType?
delaySeconds : Int?
}#external
pub type Miniflare#external
pub type Queueasync fn Queue::send_batch(self : Queue, messages : Array[MessageSendRequest], options? : QueueSendBatchOptions) -> Unitpub(all) enum QueueContentType {
Text
Bytes
Json
V8
}#external
pub type QueueEvent#external
pub type QueueMessage#external
pub type QueueMessageBatchpub(all) struct QueueRetryOptions {
delaySeconds : Int?
}pub(all) struct QueueSendBatchOptions {
delaySeconds : Int?
}#external
pub type R2Bucketasync fn R2Bucket::create_multipart_upload(self : R2Bucket, key : String, httpMetadata? : R2HttpMetadata, customMetadata? : Any, md5? : String, sha1? : String, sha256? : String, sha384? : String, sha512? : String) -> R2MultipartUploadasync fn R2Bucket::get(self : R2Bucket, key : String, onlyIf? : R2Conditional, range? : R2Range) -> R2Object?fn R2Bucket::resume_multipart_upload(self : R2Bucket, key : String, upload_id : String) -> R2MultipartUploadpub(all) struct R2HttpMetadata {
contentType : String?
contentLanguage : String?
contentDisposition : String?
contentEncoding : String?
cacheControl : String?
cacheExpiry : Date?
}#external
pub type R2MultipartUploadasync fn R2MultipartUpload::complete(self : R2MultipartUpload, parts : Array[R2UploadedPart]) -> R2Objectasync fn R2MultipartUpload::upload_part(self : R2MultipartUpload, part_number : Int, value : Any) -> R2UploadedPart#external
pub type R2Object#external
pub type R2Objectspub(all) struct R2Range {
offset : Int?
length : Int?
suffix : Int?
}pub(all) struct R2UploadedPart {
partNumber : Int
etag : String
}#external
pub type RateLimitBindingpub(all) struct RateLimitResult {
success : Bool
}#external
pub type SendEmail#external
pub type SqlStoragefn SqlStorage::exec3(self : SqlStorage, query : String, p1 : Any, p2 : Any, p3 : Any) -> SqlStorageCursor#external
pub type SqlStorageCursor#external
pub type SqlStorageIteratorResult#external
pub type TextChunkpub(all) struct TurnstileVerifyOptions {
remoteIp : String?
idempotencyKey : String?
}#external
pub type TurnstileVerifyResult#external
pub type VectorizeIndexasync fn VectorizeIndex::delete_by_ids(self : VectorizeIndex, ids : Array[String]) -> VectorizeMutationResultasync fn VectorizeIndex::get_by_ids(self : VectorizeIndex, ids : Array[String]) -> Array[VectorizeVector]async fn VectorizeIndex::insert(self : VectorizeIndex, vectors : Array[VectorizeVector]) -> VectorizeMutationResultasync fn VectorizeIndex::query(self : VectorizeIndex, vector : Array[Double], options : VectorizeQueryOptions) -> VectorizeMatchesasync fn VectorizeIndex::query_simple(self : VectorizeIndex, vector : Array[Double]) -> VectorizeMatchesasync fn VectorizeIndex::upsert(self : VectorizeIndex, vectors : Array[VectorizeVector]) -> VectorizeMutationResult#external
pub type VectorizeIndexInfo#external
pub type VectorizeMatch#external
pub type VectorizeMatches#external
pub type VectorizeMutationResultpub(all) struct VectorizeQueryOptions {
topK : Int?
returnValues : Bool?
returnMetadata : VectorizeReturnMetadata?
ns : String?
filter : Any?
}pub(all) enum VectorizeReturnMetadata {
None_
Indexed
All
}pub(all) struct WaitForEventOptions {
event : String
timeout : String?
}#external
pub type Workflowasync fn Workflow::create(self : Workflow, options : WorkflowInstanceCreateOptions) -> WorkflowInstanceasync fn Workflow::create_batch(self : Workflow, batch : Array[WorkflowInstanceCreateOptions]) -> Array[WorkflowInstance]#external
pub type WorkflowError#external
pub type WorkflowEvent#external
pub type WorkflowEventPayload#external
pub type WorkflowInstanceasync fn WorkflowInstance::send_event(self : WorkflowInstance, event_type : String, payload : Any) -> Unitfn WorkflowInstanceCreateOptions::with_id_and_params(id : String, params : Any) -> WorkflowInstanceCreateOptionspub(all) struct WorkflowRetryConfig {
limit : Int
delay : String
backoff : String
}#external
pub type WorkflowStepasync fn WorkflowStep::do_with_config(self : WorkflowStep, name : String, config : WorkflowStepConfig, callback : async () -> Any) -> Anyasync fn WorkflowStep::wait_for_event(self : WorkflowStep, name : String, options : WaitForEventOptions) -> WorkflowEventPayloadasync fn verify_turnstile_token(secret : String, response : String, options? : TurnstileVerifyOptions, endpoint? : String) -> TurnstileVerifyResultasync fn verify_turnstile_token_with_fetch(fetch_impl : Any, secret : String, response : String, options? : TurnstileVerifyOptions, endpoint? : String) -> TurnstileVerifyResultMoonBit bindings for Cloudflare Workers APIs (KV, D1, R2, Durable Objects, etc.)
Dependencies