From e1e847c8b8775a6f31fc8e6c4c4f159cbd985278 Mon Sep 17 00:00:00 2001 From: Uchio Kondo Date: Thu, 20 Aug 2026 22:40:22 +0900 Subject: [PATCH 1/3] Fix Queue secret access in Cloudflare spike --- uzumibi-on-cloudflare-spike/src/index.queue.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/uzumibi-on-cloudflare-spike/src/index.queue.js b/uzumibi-on-cloudflare-spike/src/index.queue.js index 55b0bfa..46b3966 100644 --- a/uzumibi-on-cloudflare-spike/src/index.queue.js +++ b/uzumibi-on-cloudflare-spike/src/index.queue.js @@ -189,6 +189,20 @@ export default { return 0; }, + // Secret.get(key) -> secret value from env bindings + uzumibi_cf_secret_get: (keyPtr, keySize, resultPtr, resultMaxSize) => { + const memory = exports.memory; + const key = decoder.decode(new Uint8Array(memory.buffer, keyPtr, keySize)); + const value = env[key]; + if (value === undefined || value === null) { + return -1; + } + const valueBytes = encoder.encode(String(value)); + const length = Math.min(valueBytes.length, resultMaxSize); + new Uint8Array(memory.buffer, resultPtr, resultMaxSize).set(valueBytes.slice(0, length)); + return length; + }, + // Queue.send(queue_name, message) uzumibi_cf_queue_send: async (queueNamePtr, queueNameSize, messagePtr, messageSize) => { const memory = exports.memory; From 8d644a75a4321977b91ca2b58d84027574e798aa Mon Sep 17 00:00:00 2001 From: Uchio Kondo Date: Thu, 20 Aug 2026 22:40:32 +0900 Subject: [PATCH 2/3] Fix Cloudflare Queue template integration --- uzumibi-cli/src/main.rs | 5 +++++ .../cloudflare/__features__/queue/src/index.js | 14 ++++++++++++++ uzumibi-cli/tests/runn/new_cloudflare_queue.yml | 12 +++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/uzumibi-cli/src/main.rs b/uzumibi-cli/src/main.rs index ba68b09..c2fa568 100644 --- a/uzumibi-cli/src/main.rs +++ b/uzumibi-cli/src/main.rs @@ -535,6 +535,11 @@ fn print_project_next_steps(template: &str, _project_name: &str, features: &[Str " β€’ After trying to bootstrap, edit \x1b[33mlib/app.rb\x1b[0m and \x1b[33mpublic/index.html\x1b[0m to develop your custom SPA application" ); } + "cloudflare" | "cloudrun" if has_queue => { + println!( + " β€’ After trying to bootstrap, edit \x1b[33mlib/consumer.rb\x1b[0m to develop your queue consumer" + ); + } _ => { println!( " β€’ After trying to bootstrap, edit \x1b[33mlib/app.rb\x1b[0m to develop your custom application" diff --git a/uzumibi-cli/templates/cloudflare/__features__/queue/src/index.js b/uzumibi-cli/templates/cloudflare/__features__/queue/src/index.js index c5c7f4d..b14babb 100644 --- a/uzumibi-cli/templates/cloudflare/__features__/queue/src/index.js +++ b/uzumibi-cli/templates/cloudflare/__features__/queue/src/index.js @@ -189,6 +189,20 @@ export default { return 0; }, + // Secret.get(key) -> secret value from env bindings + uzumibi_cf_secret_get: (keyPtr, keySize, resultPtr, resultMaxSize) => { + const memory = exports.memory; + const key = decoder.decode(new Uint8Array(memory.buffer, keyPtr, keySize)); + const value = env[key]; + if (value === undefined || value === null) { + return -1; + } + const valueBytes = encoder.encode(String(value)); + const length = Math.min(valueBytes.length, resultMaxSize); + new Uint8Array(memory.buffer, resultPtr, resultMaxSize).set(valueBytes.slice(0, length)); + return length; + }, + // Queue.send(queue_name, message) uzumibi_cf_queue_send: async (queueNamePtr, queueNameSize, messagePtr, messageSize) => { const memory = exports.memory; diff --git a/uzumibi-cli/tests/runn/new_cloudflare_queue.yml b/uzumibi-cli/tests/runn/new_cloudflare_queue.yml index 32a7781..da9532d 100644 --- a/uzumibi-cli/tests/runn/new_cloudflare_queue.yml +++ b/uzumibi-cli/tests/runn/new_cloudflare_queue.yml @@ -30,7 +30,9 @@ steps: command: cd {{ vars.tmpdir }} && {{ vars.binary }} new -t cloudflare --features queue {{ vars.project_name }} test: | current.exit_code == 0 && - current.stdout contains 'Successfully created project' + current.stdout contains 'Successfully created project' && + current.stdout contains 'lib/consumer.rb' && + !(current.stdout contains 'lib/app.rb') check_queue_files: desc: Check Queue-specific files and configuration @@ -50,6 +52,14 @@ steps: command: cd {{ vars.tmpdir }}/{{ vars.project_name }} && pnpm run build:wasm:queue test: current.exit_code == 0 + check_queue_wasm_imports: + desc: Check that the Queue Worker provides every WASM host import + exec: + command: >- + cd {{ vars.tmpdir }}/{{ vars.project_name }} && + node -e 'const fs = require("node:fs"); const p = require("./package.json"); const wasm = fs.readFileSync("src/" + p.name.replaceAll("-", "_") + "_queue.wasm"); const imports = WebAssembly.Module.imports(new WebAssembly.Module(wasm)).filter((item) => item.module === "env"); const source = fs.readFileSync("src/index.js", "utf8"); const missing = imports.map((item) => item.name).filter((name) => !source.includes(name + ":")); if (missing.length) { console.error("Missing WASM host imports: " + missing.join(", ")); process.exit(1); }' + test: current.exit_code == 0 + start_server: desc: Start Queue Worker dev server in background exec: From 0a6fc1b5db9f1aac5cdf2ed68a5959ab1ac76326 Mon Sep 17 00:00:00 2001 From: Uchio Kondo Date: Thu, 20 Aug 2026 22:40:41 +0900 Subject: [PATCH 3/3] Refresh general and Cloudflare documentation --- README.md | 122 ++++---- uzumibi-docs/src/SUMMARY.md | 10 +- uzumibi-docs/src/cli-reference.md | 1 - uzumibi-docs/src/cli-reference/commands.md | 134 ++------- .../src/cli-reference/common-workflows.md | 58 ++-- .../cli-reference/environment-variables.md | 19 +- .../src/cli-reference/future-commands.md | 11 - .../src/cli-reference/project-templates.md | 105 ++----- .../src/cli-reference/troubleshooting.md | 40 +-- uzumibi-docs/src/examples/error-handling.md | 2 +- uzumibi-docs/src/examples/http-methods.md | 4 +- uzumibi-docs/src/examples/json-api.md | 4 +- uzumibi-docs/src/examples/next-steps.md | 2 +- .../src/examples/real-world-example.md | 2 +- uzumibi-docs/src/external-services.md | 13 +- .../external-services/available-services.md | 273 ++++-------------- .../src/external-services/contributing.md | 16 +- .../external-services/development-roadmap.md | 21 -- .../src/external-services/next-steps.md | 5 - .../platform-support-matrix.md | 30 +- .../src/external-services/usage-examples.md | 162 +++++------ .../what-are-external-service-abstractions.md | 35 ++- .../creating-a-cloudflare-workers-project.md | 57 +++- uzumibi-docs/src/installation/deploying.md | 36 ++- .../src/installation/editing-ruby-files.md | 37 +-- uzumibi-docs/src/installation/next-steps.md | 2 +- .../src/installation/prerequisites.md | 28 +- .../src/installation/running-locally.md | 50 +--- .../src/installation/troubleshooting.md | 45 +-- uzumibi-docs/src/introduction.md | 55 ++-- uzumibi-docs/src/overview/architecture.md | 89 +++--- .../src/overview/project-structure.md | 19 +- .../src/overview/what-is-mrubyedge.md | 16 +- uzumibi-docs/src/overview/what-is-uzumibi.md | 17 +- .../src/platforms/choosing-a-platform.md | 24 +- .../src/platforms/cloudflare-workers.md | 221 +++++++++++--- uzumibi-docs/src/platforms/next-steps.md | 2 +- .../src/platforms/platform-comparison.md | 23 +- uzumibi-docs/src/ruby-api/best-practices.md | 14 +- uzumibi-docs/src/ruby-api/complete-example.md | 75 ++--- uzumibi-docs/src/ruby-api/error-handling.md | 44 +-- uzumibi-docs/src/ruby-api/helper-functions.md | 37 ++- uzumibi-docs/src/ruby-api/limitations.md | 17 +- uzumibi-docs/src/ruby-api/request-object.md | 107 +++---- uzumibi-docs/src/ruby-api/response-object.md | 91 ++---- uzumibi-docs/src/ruby-api/routing.md | 85 +++--- 46 files changed, 973 insertions(+), 1287 deletions(-) delete mode 100644 uzumibi-docs/src/cli-reference/future-commands.md delete mode 100644 uzumibi-docs/src/external-services/development-roadmap.md delete mode 100644 uzumibi-docs/src/external-services/next-steps.md diff --git a/README.md b/README.md index 3fc8c57..fba30ed 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,76 @@ -Uzumibi -========== +# Uzumibi ![Uzumibi's Logo](./logo.png) -Uzumibi is a lightweight web application framework for embedding MRuby into edge computing platforms like Cloudflare Workers, Fastly Compute@Edge, Spin and so on. It allows developers to write serverless applications using Ruby, leveraging the power of MRuby for efficient execution in constrained environments. +Uzumibi is a Ruby web framework and project generator for WebAssembly-based edge and serverless runtimes. Ruby application code is compiled to mruby bytecode at build time and executed by [mruby/edge](https://github.com/mrubyedge/mrubyedge) inside a platform-specific host. -Uzumibi uses a specialized mruby implementation [mruby/edge](https://github.com/mrubyedge/mrubyedge), which is optimized for edge computing scenarios - WebAssembly environments with limited resources. +The `uzumibi` CLI currently provides templates for: -## πŸ‘‰ Documentation +- Cloudflare Workers +- Fastly Compute +- Spin +- Google Cloud Run +- Browser Service Workers +- Browser Web Workers -- [Beginning Uzumibi](https://mrubyedge.github.io/beginning-uzumibi/) - An online book to get you up and running with Uzumibi. -- [On GitHub Pages](https://mrubyedge.github.io/uzumibi/) - The official Uzumibi documentation, covering installation, usage, supported platforms, and more. +## Documentation -### tl;dr +- [Beginning Uzumibi](https://mrubyedge.github.io/beginning-uzumibi/) +- [Uzumibi documentation](https://mrubyedge.github.io/uzumibi/) -Ruby code example for Uzumibi: +## Quick start with Cloudflare Workers -```ruby -class App < Uzumibi::Router - get "/" do |req, res| - res.status_code = 200 - res.headers = { - "content-type" => "text/plain", - "x-powered-by" => "#{RUBY_ENGINE} #{RUBY_VERSION}" - } - res.body = "It works!\nVisit /greet/to/:name to get greeted.\n" - res - end +Install the CLI and the WebAssembly target: - get "/description" do |req, res| - res.status_code = 200 - res.headers = { - "content-type" => "text/plain", - } - res.body = - "\"Uzumibi\" is a Japanese term that refers\n" + - "to live embers buried under a layer of ash\n" + - "to keep the fire from going out.\n" - res - end +~~~bash +cargo install uzumibi-cli +rustup target add wasm32-unknown-unknown +~~~ + +Create and run a project: + +~~~bash +uzumibi new --template cloudflare my-app +cd my-app +pnpm install +pnpm run dev +~~~ + +Edit `lib/app.rb` to define routes: - get "/greet/to/:name" do |req, res| - res.status_code = 200 - res.headers = { - "content-type" => "text/plain", - "x-powered-by" => "#{RUBY_ENGINE} #{RUBY_VERSION}" - } - res.body = "Hello, #{req.params[:name]}!!\n" - res +~~~ruby +class App < Uzumibi::Router + get "/" do |req, res| + res.return( + 200, + { "content-type" => "text/plain" }, + "Hello from #{RUBY_ENGINE} #{RUBY_VERSION}\n" + ) end get "/hello/:name" do |req, res| - res.status_code = 302 - res.headers = { - "location" => "/greet/to/#{req.params[:name]}", - "content-type" => "text/plain", - } - res.body = "Moved\n" - res + res.return( + 200, + { "content-type" => "text/plain" }, + "Hello, #{req.params[:name]}!\n" + ) end end $APP = App.new -``` - -...that runs on various edge platforms!! - -Crates and projects ------------------ - -- [**uzumibi-cli**](./uzumibi-cli/) - A command-line interface tool to generate Uzumibi application scaffolds to various edge platforms. - - ![crates.io](https://img.shields.io/crates/v/uzumibi-cli.svg) -- [**uzumibi-gem**](./uzumibi-gem/) - The mruby/edge gem that provides the core Uzumibi framework functionality. - - ![crates.io](https://img.shields.io/crates/v/uzumibi-gem.svg) -- [**uzumibi-art-router**](./uzumibi-art-router/) - A lightweight router library for Uzumibi, providing routing capabilities for handling HTTP requests. - - ![crates.io](https://img.shields.io/crates/v/uzumibi-art-router.svg) - -### Spike codes +~~~ -- [**uzumibi-on-cloudflare-spike**](./uzumibi-on-cloudflare-spike/) - An Uzumibi application scaffold for Cloudflare Workers (using Wasm with some JavaScript). -- [**uzumibi-on-cloudrun-spike**](./uzumibi-on-cloudrun-spike/) - An Uzumibi application scaffold for Google Cloud Run. Experimental. -- [**uzumibi-on-fastly-spike**](./uzumibi-on-fastly-spike/) - An Uzumibi application scaffold for Fastly Compute@Edge. -- [**uzumibi-on-spin-spike**](./uzumibi-on-spin-spike/) - An Uzumibi application scaffold for Spin using Fermyon Cloud. +For Cloudflare Workers, `pnpm run dev` rebuilds the Wasm module and starts Wrangler. See the [Cloudflare Workers guide](https://mrubyedge.github.io/uzumibi/platforms/cloudflare-workers.html) for request-size configuration, external services, static assets, and Queue consumers. -### ToDos +## Workspace components -- Support of wasmCloud +- [`uzumibi-cli`](./uzumibi-cli/) β€” generates platform-specific application projects +- [`uzumibi-gem`](./uzumibi-gem/) β€” defines `Uzumibi::Router`, `Request`, and `Response` +- [`uzumibi-art-router`](./uzumibi-art-router/) β€” route matching and path-parameter extraction +- [`uzumibi-cloudflare-ext`](./uzumibi-cloudflare-ext/) β€” Cloudflare host APIs exposed to Ruby +- [`uzumibi-google`](./uzumibi-google/) β€” Google Cloud integrations used by the Cloud Run template +- `uzumibi-on-*-spike` directories β€” development and integration examples for individual runtimes -## How to pronounce "Uzumibi" +## How to pronounce β€œUzumibi” -Uzumibi(γ†γšγΏγ³) is pronounced as /`oo-zΓ³o-mi-bΓ¬`/, which sounds natural when you pronounce in relaxed oo - `ʊ` +Uzumibi (γ†γšγΏγ³) is pronounced roughly as β€œoo-zoo-mee-bee.” The Japanese word refers to live embers kept under ash so that the fire does not go out. diff --git a/uzumibi-docs/src/SUMMARY.md b/uzumibi-docs/src/SUMMARY.md index c37bb92..b7327e1 100644 --- a/uzumibi-docs/src/SUMMARY.md +++ b/uzumibi-docs/src/SUMMARY.md @@ -39,12 +39,11 @@ - [Platform Comparison](./platforms/platform-comparison.md) - [Choosing a Platform](./platforms/choosing-a-platform.md) -- [External Service Abstractions](./external-services.md) - - [What are External Service Abstractions?](./external-services/what-are-external-service-abstractions.md) +- [Platform Service APIs](./external-services.md) + - [How Platform Service APIs Work](./external-services/what-are-external-service-abstractions.md) - [Available Services](./external-services/available-services.md) - - [Platform Support Matrix](./external-services/platform-support-matrix.md) - - [Usage Examples](./external-services/usage-examples.md) - - [Development Roadmap](./external-services/development-roadmap.md) + - [Feature Support Matrix](./external-services/platform-support-matrix.md) + - [Cloudflare Usage Examples](./external-services/usage-examples.md) - [Contributing](./external-services/contributing.md) # Reference @@ -56,7 +55,6 @@ - [Common Workflows](./cli-reference/common-workflows.md) - [Troubleshooting](./cli-reference/troubleshooting.md) - [Environment Variables](./cli-reference/environment-variables.md) - - [Future Commands](./cli-reference/future-commands.md) - [Updating the CLI](./cli-reference/updating-the-cli.md) - [Getting Help](./cli-reference/getting-help.md) diff --git a/uzumibi-docs/src/cli-reference.md b/uzumibi-docs/src/cli-reference.md index 4d2d63a..eaf8476 100644 --- a/uzumibi-docs/src/cli-reference.md +++ b/uzumibi-docs/src/cli-reference.md @@ -10,6 +10,5 @@ The Uzumibi CLI (`uzumibi`) is a command-line tool for scaffolding new edge appl - [Common Workflows](./cli-reference/common-workflows.md) - [Troubleshooting](./cli-reference/troubleshooting.md) - [Environment Variables](./cli-reference/environment-variables.md) -- [Future Commands](./cli-reference/future-commands.md) - [Updating the CLI](./cli-reference/updating-the-cli.md) - [Getting Help](./cli-reference/getting-help.md) diff --git a/uzumibi-docs/src/cli-reference/commands.md b/uzumibi-docs/src/cli-reference/commands.md index b5cb940..0fe47a5 100644 --- a/uzumibi-docs/src/cli-reference/commands.md +++ b/uzumibi-docs/src/cli-reference/commands.md @@ -1,119 +1,49 @@ # Commands -### `uzumibi new` +The current CLI has one subcommand: `uzumibi new`. -Create a new edge application project from a template. +## `uzumibi new` -#### Synopsis +~~~text +uzumibi new [OPTIONS] --template