跳到正文
Hacker News-首页· lastmjs·· 3 小时前精选AI 评分86

Lasm:在 Lean 中编写经形式化验证的 Node、serverless 与 edge Web 应用

Show HN: Lasm – Write formally verified webapps in Lean for Node/serverless/edge

AI 导读

Lasm 是一个将 Lean 4 程序提前编译为 WebAssembly 的工具链,支持将单一 Lean 代码库部署为 Node 服务、serverless/edge 函数、WASI 模块或浏览器应用。该工具内置 Lean、Lake 及构建工具,并结合了形式化定理证明能力,提供多种模板与多平台部署支持。

推荐理由

文章介绍了将 Lean 4 程序编译为 WebAssembly 的工具链,并提供了多平台部署与定理证明能力,读者可据此评估其在形式化验证 Web 应用开发中的适用性。

正文 · AI 翻译

面向 JavaScript 和 WebAssembly 世界的 Lean 4。Lasm 可以将普通的 Lean 4 程序提前(Ahead-of-Time)编译为 WebAssembly。单一的 Lean 代码库可以变成 Node 服务器、无服务器或边缘函数、WASI/Fastly 模块或浏览器应用。由于它是 Lean,你可以证明所部署代码的属性。旗舰示例 Conduit 是包含 117 个已证明定理的 RealWorld 应用。Lasm 在 npm 上发布,并自带 Lean、Lake 及其构建工具;你只需要 Node(或 Bun 或 Deno)。

npm create @lasm@latest my-app -- --template hono    # then: cd my-app && npm install && npm run dev

AI 代理:此 README 本身是完整的。llms.txt 是简短的索引,docs/AI.md 列出了能帮你避免走弯路的规则。

如果 Lasm 对你有所帮助,我将不胜感激你的赞助(详情见下文)。

快速事实

事实 值
当前版本 @lasm/cli 0.3.5(发布说明);npm view @lasm/cli version
安装 npm install -D @lasm/cli(bin: lasm),或无需安装:npx @lasm/cli …;新项目:npm create @lasm@latest
Lean 恰好 4.35.0(lean-toolchain:leanprover/lean4:v4.35.0);Lasm 会安装它,构建时你不需要 elan
开发于 Linux x64/arm64 (glibc 2.34+)、macOS x64/arm64、Windows x64
编译器运行于 Node ≥ 24(已测试 24.0.0、24.22.1、26.12.1);Bun 1.4.4 和 Deno 2.9.6(已测试,作为唯一运行时)
输出 带有 program.wasm 的 dist/ + JS 启动器(Node);或平台包(--target …)
Node 应用运行于 Node ≥ 24、来自任何构建机的 Linux x64/arm64(glibc 2.28+ 或 musl),以及构建机自身的操作系统;≥ 512 MB 内存
JS/npm 互操作 import Lasm.JS;你调用的每个函数对应一行 @[js "pkg" "export"];无预制绑定(指南)
Lean 中的框架 Lasm.Fetch(HTTP,每个服务器目标)、Lasm.UI(浏览器,Elm 架构,已证明 diff)、Lasm.RPC(类型化客户端/服务器 API)、Lasm.Web(DOM 和网页 API)、Lasm.KV
运行时不可用 elab 推导、#eval 风格的求值、加载 .olean、Lean 内核(准确列表);所有这些都在构建时工作
许可证 MIT (Lasm);模板、示例和 README 代码样本也使用 MIT-0
仓库 / 问题 https://github.com/Millillion/lasm · 报告 bug(包含 npx lasm --version)

平台

每一行都在 CI 中使用平台的本地运行时、镜像或模拟器进行测试。 根据项目策略,CI 绝不会部署到真实的云账户中 (各个平台的测试方式)。

部署到 lasm build Main.lean --target … 输出 自
Node 服务器或程序(任何主机、Docker/Kubernetes、Cloud Run、Fly.io、Railway、Render、Heroku、DigitalOcean) node(默认) dist/ → node dist/main.mjs 0.1.0
AWS Lambda (.zip, nodejs24.x) lambda lambda.zip 0.1.0
AWS Lambda(容器镜像) lasm init … --deploy lambda Dockerfile.lambda 0.1.0
Lambda@Edge lambda-edge lambda-edge.zip 0.1.0
Vercel Functions vercel .vercel/output 0.1.0
Netlify Functions netlify netlify/functions/lasm 0.1.0
Azure Functions azure azure-functions/ 0.1.0
Google Cloud Functions (gen2) gcf gcf/ 0.1.0
Cloudflare Workers workers workers/ 0.2.0
Vercel Edge vercel-edge api/lasm.mjs, api/_lasm/ 0.2.0
Netlify Edge netlify-edge netlify/edge-functions/lasm.mjs 0.2.0
Deno Deploy deno-deploy deno/main.mjs 0.2.0
Supabase Edge Functions supabase-edge supabase/functions/<name>/ 0.2.0
Bun (≥ 1.3.14) / Deno (2.x) bun / deno bun/main.mjs / deno/main.mjs 0.2.0
Fastly Compute fastly bin/main.wasm, pkg/<name>.tar.gz 0.3.0
WASI (wasmtime, wasmer, node:wasi) wasi wasi/main.wasm 0.3.0
wasi-http (wasmtime serve, Spin) wasi-http wasi-http/main.wasm 0.3.0
浏览器(Chrome、Edge、Firefox、Safari) browser(或 Vite 插件 @lasm/cli/vite) dist/ 静态网站 0.3.0

Node 构建拥有 Lean 的完整运行时(线程、文件、进程、套接字)。边缘、Bun/Deno、WASI 和浏览器构建运行单线程的 Lean,没有套接字或进程(也没有文件,WASI 除外);Lean 的其余部分均可正常工作。

从这里开始

我想构建…… 运行 然后查看
命令行程序 npm create @lasm@latest my-tool examples/hello、examples/wasi-cli
Node 上带 npm 框架的 REST API npm create @lasm@latest my-api -- --template hono(或 express、fastify) examples/js-crud(Postgres + JWT、Express 和 Hono)
纯 Lean 服务器(无 npm) npm create @lasm@latest my-api -- --template fetch(任意目标)或 --template std-http(Node,亦可本地 Lean) examples/fetch;std-http 模板
一个无服务器函数(Lambda、Vercel、Netlify、Azure、GCF) npm create @lasm@latest my-fn -- --template hono --deploy lambda-zip(或 vercel、netlify、azure、gcf、lambda-edge) docs/deploy
一个边缘函数(Workers、Vercel/Netlify Edge、Deno Deploy、Supabase) npm create @lasm@latest my-edge -- --template hono --deploy workers(或 fetch) examples/edge-pure、docs/EDGE.md
一个 Fastly、WASI 或 Spin 服务 npm create @lasm@latest my-svc -- --template fetch --deploy fastly(或 wasi-http、spin、wasi) examples/fetch、docs/WASI.md
一个浏览器应用 npm create @lasm@latest my-web -- --template web examples/ui(计数器、带证明的 TodoMVC、功能演示、基准测试)
一个完整的现实世界应用(API、浏览器前端、SQL、鉴权),带证明,运行在 Node、Workers 或 Bun 上 cd examples/conduit && npm install && npm run build && npm start examples/conduit,旗舰示例(见下方)
一个带有已验证 API 的全栈应用 npm create @lasm@latest my-app -- --template fullstack templates/fullstack
要在 Lean 中调用 npm 包或 fetch 添加 import Lasm.JS 以及每个函数一行 @[js] examples/js-fetch、JS 绑定
要在 Bun 或 Deno 上运行 bun create @lasm my-app --template hono / deno run -A npm:@lasm/create my-app --template hono docs/BUN_DENO.md

每个示例都包含一个带有一条命令运行说明的 README;examples/README.md 列出了所有这些示例。

旗舰示例:Conduit,包含 117 个已证明的定理

examples/conduit 是 Conduit,即 RealWorld 应用(一个 Medium 克隆版),完全用 Lean 编写:包括 REST API、服务端渲染的浏览器应用以及证明。

  • 关于实际运行代码的 117 个定理,经检查不包含 sorry,且仅使用 Lean 的标准公理(npm run proofs;PROOFS.md 用通俗易懂的英文列出了每一个定理)。它们涵盖了授权(只有作者可以修改自己的文章和评论)、关注与收藏、永不冲突的 slug、永不跳过或重复的分页、客户端与服务器共享的验证(应用绝不会发送服务器会拒绝的内容)、JSON 往返以及 Markdown 链接安全性。这些端点是针对函数的 Store 编写的,并且证明在表格模型上运行了相同的代码。
  • 受信任但未证明的部分:每个 SQL 语句都符合其模型所描述的行为、JSON 文本层、请求并发性,以及 Lean、Lasm 和 JavaScript 运行时。对整个 RealWorld 规范的符合性是通过测试而非证明来保证的。
  • API:官方 RealWorld API 套件在 Node(node:sqlite)、Cloudflare Workers(D1)和 Bun(bun:sqlite)上未作修改即可通过(13 个文件中的 13 个,154 个请求)。每个目标都有一个手写的 @[js] 绑定模块。
  • 前端:在 RealWorld 官方模板上的 Lasm.UI,具备服务端渲染、水合作用(hydration)以及在 Lean 中解析的 Markdown。官方的 Playwright 端到端套件在配备 Chromium、Firefox 和 WebKit 的 Node 上,以及配备 Chromium 的 Workers 和 Bun 上通过,无需重试。

所有这些都在 CI 中运行(conduit.yml,运行编号 40615274657,使用 @lasm/cli 0.3.4)。

cd examples/conduit
npm install                                   # @lasm/cli, Hurl and Playwright (the official suites' runners)
npm run build && npm start                    # http://localhost:3000: the app and its API on Node
npm run proofs                                # check all 117 theorems
npm test                                      # the official API suite (also test:workers, test:bun)
npx playwright install chromium && npm run test:e2e   # the official end-to-end suite
npm run build:workers && npx wrangler dev     # Cloudflare Workers with local D1
npm run build:bun && npm run start:bun        # Bun with bun:sqlite

60 秒快速开始

单文件无需项目。将这个完整的程序保存为 Main.lean:

def main : IO Unit := do
  IO.println s!"Hello from Lean! 2 + 3 = {2 + 3}"
npx @lasm/cli Main.lean          # builds and runs: Hello from Lean! 2 + 3 = 5
npx @lasm/cli build Main.lean    # writes dist/; run it with: node dist/main.mjs

在新机器上的首次构建会获取一次 Lean 和构建工具(大约 250–275 MB;在 Linux CI 运行器上首次构建耗时 19 秒)。后续对单行代码更改的开发构建大约需要 1–2 秒。

操作指南

每个指南都是完整的:创建、开发、构建、部署。Lasm 从不安装或启动平台自身的 CLI(wrangler、vercel、fastly 等);这些需要由你来运行。npm run dev 是 lasm dev:它在每次保存后大约 2 秒重新构建并重启服务器,并且在出现类型错误时保持上一个良好的构建继续运行。

Node 服务器(Hono;同时支持 express、fastify、std-http、fetch)。

npm create @lasm@latest my-api -- --template hono
cd my-api && npm install
npm run dev                                   # http://localhost:3000/hello/Ada
npm run build && npm start                    # dist/ needs only Node 24+
docker build -t my-api . && docker run -p 8080:8080 my-api   # the generated Dockerfile

AWS Lambda / Vercel / Netlify / Azure / Google Cloud Functions。

npm create @lasm@latest my-fn -- --template hono --deploy lambda-zip   # or vercel, netlify, azure, gcf, lambda-edge
cd my-fn && npm install
npm run build:lambda                          # dist/ and lambda.zip (handler lasm-lambda.handler)
# deploy lambda.zip with the AWS console, aws CLI or SAM; recipes: docs/deploy/lambda.md

Cloudflare Workers(以及 Vercel Edge、Netlify Edge、Deno Deploy、Supabase)。

npm create @lasm@latest my-edge -- --template hono --deploy workers
cd my-edge && npm install
npm run build:workers                         # workers/ (wrangler.toml came from lasm init)
npx wrangler dev                              # local workerd; npx wrangler deploy to publish

Fastly Compute、WASI、Spin。

npm create @lasm@latest my-svc -- --template fetch --deploy fastly --deploy spin
cd my-svc && npm install
npm run build:fastly && fastly compute serve  # Viceroy on http://127.0.0.1:7676
npm run build:wasi-http && spin up            # or: wasmtime serve wasi-http/main.wasm

浏览器应用。

npm create @lasm@latest my-web -- --template web
cd my-web && npm install
npm run dev                                   # http://127.0.0.1:5173, live reload
npm run build                                 # dist/: a static site for any host or CDN

全栈(服务端 + 浏览器 + 已验证 API)。

npm create @lasm@latest my-app -- --template fullstack
cd my-app && npm install
npm run dev                                   # one URL: http://127.0.0.1:3000
npm run build && npm start                    # Node; also build:workers, build:bun, build:deno

编辑器。每个项目运行一次 npx lasm editor;lasm init、lasm dev 和 lasm build 也会这样做。随后 Lean 编辑器(VS Code 的 Lean 4 扩展)会解析 import Lasm.*(详情)。

Lean 中的整个栈,经过验证

fullstack 模板是一个包含服务端(Lasm.Fetch)、浏览器应用(Lasm.UI)以及两者间 API(Lasm.RPC)的 Lean 项目。请求必须满足的规则在 Shared.lean 中编写并证明了一次,双方都会导入该文件(templates/fullstack):

-- Shared.lean
@[irreducible] def checkTitle (title : String) : Except String Unit :=
  let n := (clean title).length
  if n = 0 then .error "Write something first."
  else if n > maxTitle then .error s!"Keep it under {maxTitle} characters."
  else .ok ()

/-- Proved once, holds in the browser and on the server. -/
theorem checkTitle_ok {title : String} (h : checkTitle title = .ok ()) :
    0 < (clean title).length ∧ (clean title).length ≤ maxTitle := by
  unfold checkTitle at h
  by_cases h0 : (clean title).length = 0
  · simp [h0] at h
  · by_cases h1 : (clean title).length > maxTitle
    · simp [h0, h1] at h
    · omega

def addTodo : Endpoint NewTodo Todo := { name := "addTodo", validate := fun r => checkTitle r.title }
-- Server.lean: storing a todo demands the proof that its title passed the check,
-- and `addTodo.serve` hands the handler that proof (`ok`) after re-validating.
def Store.add (s : Store) (title : String) (_ : checkTitle title = .ok ()) : Store × Todo :=
  let t := { id := s.next, title := clean title, done := false }
  ({ todos := s.todos.push t, next := s.next + 1 }, t)

  addTodo.serve fun req ok => do
    let (s, t) := (← load kv).add req.title ok
    save kv s
    return .ok t
-- Client.lean: a theorem about the browser app: it never sends an invalid title.
theorem add_invalid (m : Model) (e : String) (h : checkTitle m.draft = .error e) :
    (update .add m).2.effects = [.msg (.added (.error (.invalid e)))] :=
  addTodo.call_invalid { title := m.draft } Msg.added "" e h

证明所在的位置以及如何进行检查。

证明 位置 检查方式
你的定理(如 checkTitle_ok、add_invalid) 你的 .lean 文件 每个 lasm build/lasm dev(由 Lean 进行精化;证明错误即为构建错误);纯模块也使用 lake build
Lasm.RPC:处理程序仅在通过 validate (Endpoint.decodeRequest_valid) 的请求上运行;客户端从不发送未通过该验证的请求 (Endpoint.call_invalid) library/Lasm/RPC 每次构建时编译到 Lasm 的库中
Lasm.UI:DOM diff 相对于 DOM 模型是正确的,包含带键的移动(diff_correct、mount_correct、session_correct) library/Lasm/UI/Proofs(约 1,260 行,无 sorry,仅标准公理) 检出版本中的 node scripts/ui/lean-tests.mjs(CI:ui.yml)
Conduit:关于授权、关注、收藏、slug、分页、共享验证、JSON 往返和 Markdown 链接安全性的 117 个定理 examples/conduit/Proofs,列在 PROOFS.md 中 examples/conduit 中的 npm run proofs(无 sorry,仅标准公理;CI conduit.yml)
TodoMVC:每个可达模型都是有效的 examples/ui/todomvc/Todo.lean lasm build;CI ui.yml

未经验证,在 CI 中进行测试:客户端与服务端之间的 JSON/HTTP 传输、将补丁应用到真实 DOM 的 JavaScript、Lasm 编译器与运行时、以及浏览器。Lean 自身的编译器是受信任的,如同任何 Lean 程序一样(UI.md、RPC.md)。

从 Lean 调用 JavaScript 和 npm

用单行代码声明你调用的每个 JavaScript 函数;Lean 类型说明了值的转换方式。一个完整的程序(Node 的全局 fetch):

import Lasm.JS
open Lasm.JS

/-- `await fetch(url, init)` (Node's global fetch) -/
@[js "globalThis" "fetch"] opaque fetch : String → Data → IO Value

def main : IO Unit := do
  let response ← fetch "https://example.com" (obj [])
  IO.println s!"{← response.get "status" Nat}: {(← response.callMethodAwait "text" #[] String).length} characters"

编写绑定(bindings)的规则:

  • @[js "module" "export"] opaque name : A → B → IO R 绑定 module.export。该模块是一个 npm 包("marked")、Node 内置模块("node:fs"),或者是用于全局变量的 "globalThis"。"new Hono" 调用构造函数,而 "" 是模块自身的值。
  • 对于立即返回的值,类型以 IO R 结尾;对于 Promise,以 Async R 结尾。Async 绑定在等待(awaited)时不会占用 Lean 线程。
  • 使用 String、Nat、Int、Float、Bool、ByteArray、Array、List、Option、元组、Data(任何 JS 数据)或 Value(JS 对象引用:get、callMethod、callMethodAwait)。你自己的结构体可以通过 deriving ToJS, FromJS 进行转换。
  • Function.ofFn / Function.ofFnReply 将 Lean 函数转换为 JS 回调。框架处理程序会使用它们(参见 hono、express 和 fastify 模板)。
  • npm install 是 lakefile 旁边的包。lasm build 针对已安装的包(Lasm.JS binding check failed: … export "x" is missing)检查每个绑定,并将生产依赖项复制到 dist/node_modules 中。
  • 每次调用都会从 Lean 线程跨越到 Node 的主线程(约 24 µs),因此请倾向于使用一个粗粒度调用,而不是多个小调用。

完整指南,包含 Express、Hono、pg、jose 和 fetch 示例以及代理检查清单:docs/JS_BINDINGS.md。

测得的数据

所有数据均来自免费 GitHub 运行器(4-CPU AMD EPYC,Linux x64)上的 CI,候选版本 0.1.0-experimental.40494203854 (2026-10-27),除非另有说明。完整表格、方法与注意事项:BENCHMARKS.md。

指标 数值
Node:Hono + Lean 处理程序,冷启动到首次 HTTP 响应 159 ms(纯 Node http:快 4.1 倍)
Node:Hono + Lean 处理程序,吞吐量 / p99 延迟 24,911 req/s / 4.2 ms(纯 Node http:103,134 req/s,即 0.24 倍)
Node:Express + Lean 处理程序,吞吐量 18,678 req/s
Node:Hono 应用 program.wasm (brotli) / dist/ 166 KiB / 8.5 MiB 另加 1.4 MiB node_modules
Node:内存,Hono 应用空闲 / 负载下 148 MiB / 329 MiB RSS
Lean → JS 调用往返(p50) 24 µs
Cloudflare Workers:Hono 应用包 1.40 MiB, 245 KiB gzip(限制 64 MiB;workers 运行 40128600109)
浏览器:计数器应用总传输量 / 首帧(Chromium) 152 KiB brotli / 30 ms(browser 运行 40288509500)
浏览器:js-framework-benchmark 对比手写 JS 所有操作均在 1.7× 以内,多数在 1.2× 以内(browser 运行 40302274897)
WASI:在 Fastly 的 Viceroy 上每个请求对应 Lasm.Fetch 模块 0.90 MiB / 1.17 ms,每个请求使用全新实例(wasi 运行 40293231963)
构建:干净的 Hono 构建 / 单行更改后的开发重建 4.7 s / 2.0 s
npm install @lasm/cli:下载 / 已安装;首次构建后的工具缓存 71 MiB / 403 MiB;2.5 GB

Node 上的 Lean 需要为 WebAssembly 及其线程付出开销。冷启动是 CPU 密集型的,因此它在小型无服务器 CPU 份额上会增长,并且每个 JavaScript 调用都会跨越线程。纯 Lean Std.Http 在 Node 上较慢(1,290 req/s),因此生产环境 HTTP 请使用 Hono、Express、Fastify 或 Lasm.Fetch。带有数千位数字的算术运算比原生 Lean 慢(无 GMP)。

已知限制

  • 仅限 AOT(预先编译)。已部署的程序在运行时不能进行 Lean 的精化(elaborate)、求值或编译,不能加载模块数据或插件,也不能使用 Lean 的 C++ 编译器/内核(确切列表)。证明、策略、宏和 #eval 照常在编译时运行。
  • 仅限 Lean 4.35.0。其他 lean-toolchain 版本会被拒绝并显示提示信息。
  • Node:请给应用至少 512 MB 内存;它预留约 22 GB 虚拟地址空间。无法链接预构建的原生库(-l、共享库);软件包中自带的 C 源码会为你进行编译。
  • Edge、Bun/Deno、浏览器、WASI:单线程 Lean;无套接字、进程或信号;除 WASI 外无文件。在浏览器中,阻塞等待会停止应用,除非它是为带有 JSPI 的浏览器使用 --suspend jspi 构建的;请使用 Async。
  • 无预制绑定(针对 npm 软件包);Lasm.Web 涵盖核心 Web 平台。
  • 编辑器:在进行上述 npx lasm editor 操作后,编辑器中的 Lasm.* 导入才能解析。
  • 平台:不支持 Windows ARM64 以及 Alpine/musl 构建机器(构建的应用可在 Alpine 上运行)。托管平台使用其本地工具进行测试,从不使用真实账户。

文档


支持 Lasm

如果 Lasm 对你有所帮助,或者你希望看到它成功,我将不胜感激你的赞助:github.com/sponsors/lastmjs。这支持了我以及针对 Lasm 和其他 Millillion 项目的工作。我的第一个目标是每月 250 美元,这足够为一个 Lasm 专用的 Claude Code 账户提供资金。你也可以通过给仓库点星、试用它以及报告崩溃问题来提供帮助。

参考

以下所有内容都是精确的契约:每个命令和选项、支持的机器和平台,以及已部署的 Lean 程序绝对无法执行的操作。

CLI 参考

使用 npm install -D @lasm/cli 在项目中安装(bin 为 lasm),或直接运行而无需安装:npx @lasm/cli Main.lean。npm create @lasm 运行相同 lasm init 版本的 @lasm/cli,参数保持不变。使用来自 快速入门 的 Main.lean:

npx lasm Main.lean                          # build (dev profile) and run: Hello from Lean! 2 + 3 = 5
npx lasm build Main.lean                    # write dist/ (release profile)
npx lasm --version                          # version, Lean, runtime and platform (for bug reports)
node dist/main.mjs                          # run the deployment: only Node is needed
npx lasm build Main.lean --target lambda    # dist/ and an AWS Lambda zip
命令或选项 示例 效果
运行(默认) npx lasm Main.lean 构建(dev 配置)并运行 Lean main。plain 项目中的 npm run dev 会运行此命令。
显式运行 npx lasm run Main.lean 与默认命令相同。
运行 release 构建 npx lasm Main.lean --release 构建并运行 lasm build 部署的精确内容。
程序参数 npx lasm Main.lean -- hello "two words" 向 main (args : List String) 传递参数。
监视、重新构建、重启 (0.3.0) npx lasm dev, npx lasm dev Main.lean --target workers -- arg 监视 Lean 源码以及 Lake/npm 配置,在每次更改后重新构建(dev 配置,一个长生命周期的构建工作进程)并重启程序(--target node、bun、deno;默认:运行 Lasm 的运行时)。构建错误会连同其文件、行号和源码行一起打印出来;最后一个正常的程序会继续运行。边缘目标仅重新构建其输出目录,由平台自身的本地服务器提供服务(Lasm 从不启动平台工具或浏览器)。--target browser 以实时重载(--port、--host、--no-watch)提供应用服务;多个输出同时构建:--target node=Server.lean,browser=Client.lean。--release 构建 release 配置,--no-run 仅重新构建,rs + Enter 重新构建并重启。详情。
构建 npx lasm build Main.lean 写入 dist/(release 配置);不运行应用程序。
Dev 构建 npx lasm build Main.lean --dev 更快地写入 dist/,不进行体积优化。
输出目录 npx lasm build Main.lean --output "app dist" 选择部署目录。lasm build Main.lean "app dist" 是一个别名。
函数平台 npx lasm build Main.lean --target lambda 构建 dist/,然后对其进行打包:node(默认;仅 dist/)、lambda(lambda.zip)、lambda-edge(lambda-edge.zip)、vercel(.vercel/output)、netlify(netlify/functions/lasm)、azure(azure-functions/)、gcf(gcf/)。--target=vercel 同样有效。Lasm 从不安装或启动平台的 CLI。操作指南。
边缘隔离 (0.2.0) npx lasm build Main.lean --target workers 使用纯 JS 主机重新链接单线程:workers(workers/)、vercel-edge(api/lasm.mjs、api/_lasm/)、netlify-edge(netlify/edge-functions/lasm.mjs、netlify/lasm/)、deno-deploy(deno/main.mjs)、supabase-edge(supabase/functions/<name>/;Asyncify,因为 Supabase 的运行时没有 JSPI)。边缘运行时内置于 @lasm/cli 中。指南:Workers、Vercel Edge、Netlify Edge、Deno Deploy、Supabase;设计与限制。
Bun 和 Deno (0.2.0) bunx --bun @lasm/cli Main.lean, deno run -A npm:@lasm/cli Main.lean, bun create @lasm my-app --template hono 编译器以 Bun 或 Deno 作为其唯一的 JavaScript 运行时运行,并产生相同的字节。在 Bun 或 Deno 下,默认目标是该运行时:--target bun 写入 bun/main.mjs,--target deno 写入 deno/main.mjs(便携配置)。Deno 会跳过发布时间不到 24 小时的 npm 版本:发布后立即通过 --minimum-dependency-age=0。Bun 和 Deno。
浏览器 (0.3.0) npx lasm build Main.lean --target browser 将 dist/ 写入为静态网站:app.<hash>.js(加载器:mount(element, { flags, hydrate }),自动挂载 <div data-lasm-app>)、app.<hash>.wasm、brotli 和 gzip 副本、app.js、index.html(带有注入加载器的你的页面,或生成的页面)、你的 public/ 文件和 lasm-manifest.json。--suspend jspi 允许阻塞等待在浏览器拥有 JSPI 的地方暂停。--bundler 将 npm 导入留给打包工具;在 Vite 中:import lasm from '@lasm/cli/vite',然后 import app from './Main.lean?lasm'。来自 Lean 的 Web API:import Lasm.Web。指南:BROWSER.md、UI.md、部署。
WASI、wasi-http、Fastly (0.3.0) npx lasm build Main.lean --target wasi(或 wasi-http、fastly) 没有 JavaScript。wasi 写入 wasi/main.wasm(wasi_snapshot_preview1:wasmtime run --dir . wasi/main.wasm,wasmer,node:wasi);wasi-http 写入 wasi-http/main.wasm,一个 wasi:http/proxy@0.2 组件(wasmtime serve,Spin);fastly 写入 bin/main.wasm 和 pkg/<name>.tar.gz(fastly compute serve/deploy)。没有套接字、进程或信号。WASI.md、Fastly。
纯 Lean 中的 HTTP (0.3.0) import Lasm.Fetch … def main := Lasm.Fetch.serve handle 一个 Request → Async Response 处理器为 Node($HOST:$PORT)、边缘目标、Bun、Deno、Fastly、wasi-http 和作为 CGI 的 WASI 提供服务;Lasm.Fetch.fetch 发送请求;Response.streaming 流式传输。FETCH.md。
强制重新构建 npx lasm build Main.lean --rebuild 忽略缓存的应用构建。
详细诊断 npx lasm Main.lean --verbose 显示编译器和链接器详情。
帮助 npx lasm --help, npx lasm init --help 显示用法;-h 是一个别名。
版本 npx lasm --version 打印 lasm 0.3.5 (@lasm/cli; Lean 4.35.0; Node 26.12.1; linux-x64);-v 是一个别名。
新项目 npm create @lasm@latest my-app -- --template hono 或 npx @lasm/cli init my-app --template hono 在新的或空目录中创建一个 Lake 项目(Main.lean、App.lean、lakefile、lean-toolchain、package.json、README.md、.gitignore,对于服务器还包括一个 Dockerfile 和 .dockerignore)。模板:参见 从这里开始。--deploy(可重复)添加平台的文件和 npm run build:<target>:lambda(Dockerfile.lambda,一个容器镜像)、lambda-zip、lambda-edge、vercel、netlify、azure、gcf;workers、vercel-edge、netlify-edge、deno-deploy(模板 hono、fetch、fullstack)、supabase-edge(hono);fastly、wasi-http、spin(fetch、fullstack)、wasi(fetch、plain)。fetch 和 fullstack 模板及其目标属于 0.3.0 版本。仅写入文件;接下来请运行 npm install。-t 是 --template 的别名;--template=hono 也可以使用。
打包现有构建 npx lasm package --target lambda 打包已构建的服务器(默认 dist/),用于函数平台,无需重新构建:目标和输出与 lasm build --target 相同,但 node 除外。--output PATH 用于选择输出。检查平台的大小限制。除非满足 --allow-dev,否则拒绝开发版构建。对于浏览器构建,npx lasm package dist --target browser 会对照 lasm-manifest.json 检查每个文件并写入 _headers。
编辑器支持 (0.3.0) npx lasm editor 使 Lean 编辑器(VS Code 的 Lean 4 扩展、任何 Lean 语言服务器客户端)解析此 Lake 项目中的 import Lasm.*:将 Lasm 的 Lean 4.35.0 及其库链接为 elan 工具链 lasm-4.35.0-…,并将其设置为该目录的 elan 覆盖(elan override unset 可撤销此操作)。当 Lasm 的 Lean 已经安装时,lasm init、lasm dev 和 lasm build 会执行相同操作,每个项目打印一行,但在 CI 中或使用 LASM_EDITOR=0 时除外。编辑器设置。
缓存修复 npx lasm cache repair 离线验证并移除无效工具和废弃的暂存区。拒绝处于活动状态的构建。

--rebuild 和 --verbose 适用于运行和构建。--output 和 --target 仅用于 构建;-- 之后的参数仅用于运行。应用程序的退出状态会 予以保留。npx lasm --version(-v)打印版本、Lean 发行版、JavaScript 运行时和平台(请将其包含在错误报告中)。没有 install、clean 或 uninstall 子命令。

构建配置文件。两者使用相同的库链接相同的程序,且都是 确定性的。release(lasm build、lasm Main.lean --release):完整的 Binaryen 大小优化;字节级可复现;用于部署的版本。dev (lasm Main.lean、lasm dev、lasm build --dev):省略这些优化通道,并在 -O1 下编译您的模块;其行为相同,构建速度快几秒钟, 且其 program.wasm 大约大 15–20%。开发版重新构建从 项目的上一次构建开始,因此其字节可能取决于该次构建。build-info.json 记录了 "profile"。除非您传入 --allow-dev,否则 lasm package 和 lasm build --dev --target <platform> 会拒绝开发版构建。

环境变量(全部可选):

变量 示例 效果
LASM_TOOLCHAIN_CACHE LASM_TOOLCHAIN_CACHE=/data/lasm-cache npx lasm Main.lean 移动托管工具缓存(默认位置)。
LASM_BUILD_JOBS LASM_BUILD_JOBS=2 npx lasm build Main.lean Binaryen 优化器的线程数(默认:CPU 数量,最多 8 个)。无论什么值,输出都相同。
LASM_EDITOR LASM_EDITOR=0 npx lasm build Main.lean 0:lasm init、lasm dev 和 lasm build 不干预编辑器设置(编辑器设置)。
LASM_THREAD_POOL(已构建的应用;0.3.0) LASM_THREAD_POOL=0 node dist/main.mjs 在 main 之前启动的 Lean 线程工作进程(0–64,默认 1)。测量数据。
LASM_ARTIFACT_SOURCE LASM_ARTIFACT_SOURCE=npm npx lasm Main.lean auto(默认):存在时使用 @lasm/… npm 工具包,否则使用 HTTPS;npm:从不直接下载;https:忽略 npm 包。
LASM_DOWNLOAD_ATTEMPTS、LASM_DOWNLOAD_CONNECT_MS、LASM_DOWNLOAD_IDLE_MS、LASM_DOWNLOAD_TOTAL_MS LASM_DOWNLOAD_TOTAL_MS=14400000 npx lasm Main.lean 下载重试和超时(默认值和范围)。
NODE_USE_ENV_PROXY、HTTPS_PROXY、NO_PROXY、NODE_EXTRA_CA_CERTS(Node 自带) NODE_USE_ENV_PROXY=1 HTTPS_PROXY=http://proxy:8080 npx lasm Main.lean 代理和私有 CA(企业网络)。

源码中的其他 LASM_* 变量属于维护者诊断信息,并非受支持的 接口。

安装。 npm install @lasm/cli 通过您自己的注册表、代理和缓存,为您的平台将 Lean 和构建工具作为精确锁定的 @lasm/… npm 包引入。Lake/Lean-import 数据,以及仅针对包含 C 代码的 Lake 项目的 C 层(@lasm/lean-c-<platform>),在首次使用时通过您的 npm 获取。 终端会显示进度;后续构建会复用已验证的工具和未更改的输出。在一台没有下载缓存的新机器上,CI 运行器上的首次 Hono 构建耗时为 25.7 秒(Linux x64)、27.8 秒(Linux arm64)、44.4 秒(Windows)、58.7 秒(Apple Silicon)和 141.9 秒(Intel Mac) (构建时间,运行 40131930601)。 缓存位置与恢复:NODE_SUPPORT.md、 INSTALLATION_HARDENING.md。 仅当 Lake 项目具有 Git 或 Reservoir 依赖项时才需要 Git;Lasm 使用您 PATH 上的 git,并在缺少时提示如何安装。

现有的 Lake 项目可以直接在项目目录中使用 npx lasm build Main.lean 进行构建。在 lean-toolchain 中锁定 leanprover/lean4:v4.35.0;其他版本会被 Unsupported Lean toolchain … Lasm supports Lean v4.35.0 拒绝。按软件包列出的兼容性列表涵盖了 Batteries、Cli、LSpec、Plausible、Aesop、Qq、leansqlite、UnicodeBasic、MD4Lean、lean-zip、lean4-parser、lean-redis 等;未列出的软件包未经测试。

支持的环境

使用 Lasm(编译器)构建的机器:

环境 架构 状态
Ubuntu 24.04 LTS x86-64、ARM64 在 CI 中接受已安装软件包和复制部署验证;参考平台。
其他 Linux 发行版 x86-64、ARM64 未作为构建机器进行验证;这些工具需要 glibc 2.34。Alpine/musl 不能作为构建机器(构建的应用可在其上运行)。
macOS 15 x86-64、ARM64 在 CI 中接受已安装软件包和复制部署验证。带有 C 代码的 Lake 项目需要 Xcode Command Line Tools SDK。
Windows Server 2025 / Windows x64 x86-64 在 CI 中接受已安装软件包和复制部署验证。
Windows ARM64 ARM64 不支持:Lean 和 Emscripten 均未发布 Windows ARM64 预构建版本。
作为编译器运行时的 Bun 1.4.4 和 Deno 2.9.6 (0.2.0) 上述所有 在 CI 的全部五个平台上进行测试,在 PATH 上运行且不依赖 Node 或 npm(BUN_DENO.md)。

Node 24 或更高版本(已测试:24.0.0、24.22.1、26.12.1)。无引擎标志。精确测试的产物:NODE_ACCEPTANCE.md。

支持的平台

Node dist/ 需要 Node 24 或更新版本(Node 22 及更早版本会通过 This application requires Node 24.0.0 or newer 终止)以及至少 512 MB 内存。它可在 Linux x64 和 arm64(glibc 2.28+ 或 musl/Alpine)上运行(这些平台可以由任何支持的平台构建,也可以在其自身的构建机器平台上运行)。复制 dist/ 的所有内容;那里不需要 Lean 源码、npm install 或构建工具。下方的每个平台都在 CI 中通过命名的本地运行时、镜像或模拟器进行了测试;均未使用真实的云账号。完整矩阵:DEPLOYMENT.md。

平台 在 CI 中测试的环境
Linux x64 和 arm64 (glibc 2.28+)、Node 24+ ubuntu-24.04 和 ubuntu-24.04-arm 上的 Node 24.0.0、24.22.1 和 26.12.1
macOS (x64、arm64) macos-15-intel 上的 Node 24.0.0 和 24.22.1;macos-15 上的 Node 24.22.1;使用 Node 26.12.1 进行安装验证
Windows x64 windows-2025 上的 Node 24.0.0 和 24.22.1;使用 Node 26.12.1 进行安装验证
Docker / Kubernetes node:24-bookworm-slim、node:26-bookworm-slim、node:24-bullseye-slim,Ubuntu 22.04/24.04;只读,512 MB,x64 和 arm64(Kubernetes 清单未在 CI 中应用)
Google Cloud Run、Fly.io、Railway、Render、Heroku 相同的容器镜像和 Dockerfile;这些平台本身从未被部署到
AWS Lambda(容器镜像) public.ecr.aws/lambda/nodejs:24 + 通过运行时接口模拟器(Runtime Interface Emulator)的 AWS Lambda Web Adapter,x86_64 和 arm64;amazonlinux:2023
AWS Lambda (.zip, nodejs24.x) 通过 Runtime Interface Emulator 在 public.ecr.aws/lambda/nodejs:24 中运行每个服务器模板的 --target lambda zip,支持 x86_64 和 arm64,以及 API Gateway REST/HTTP、函数 URL 和 ALB 事件;sam local invoke 和 sam local start-api
Lambda@Edge (origin request, x86_64) 具有 CloudFront origin-request 事件的相同镜像和模拟器
Vercel Functions (Node.js 24) vercel build 离线;位于 public.ecr.aws/lambda/nodejs:24 中 @vercel/node 下方的函数
Netlify Functions (v2) netlify build --offline 和 netlify dev --offline;位于 public.ecr.aws/lambda/nodejs:24 中的部署 zip
Azure Functions (Node.js v4 model, Linux) Azure Functions Core Tools func start
Google Cloud Functions (gen2, nodejs24) Ubuntu 24.04 上的 Functions Framework;Google Cloud 的 buildpacks 镜像
Alpine/musl 容器 node:24-alpine、node:26-alpine,x64 和 arm64,只读,512 MB
DigitalOcean App Platform (gVisor) gVisor runsc 下的容器镜像,x64
Cloudflare Workers (0.2.0) wrangler dev 4.152.0 (workerd),带有 Free 计划的预算限制
Vercel Edge (0.2.0) vercel build 离线且 Vercel 的 edge-runtime
Netlify Edge (0.2.0) netlify build --offline 和 netlify dev --offline
Deno Deploy (0.2.0) 运行 deno/main.mjs 的 Deno 2.9.6
Supabase Edge Functions (0.2.0) Docker 中的 Supabase edge-runtime v1.77.8 镜像
Bun 和 Deno 程序 (0.2.0) 所有五个平台上的 Bun 1.4.4 和 Deno 2.9.6
WASI, wasi-http, Spin, Fastly (0.3.0) wasmtime 49.0.4 (run, serve), wasmer 7.4.2, Node 的 node:wasi, Spin 4.2.2, Viceroy 0.21.1 (wasi.yml)
浏览器 (0.3.0) Playwright 1.63.0:ubuntu-24.04 上的 Chromium 153 和 Firefox 155;ubuntu-24.04 和 macos-15 上的 WebKit 26.6 (browser.yml)

在 Windows 上构建并复制到 Linux(非通过 docker build 复制)的 dist/ 需要 chmod 755 dist/host/native/process/linux-*。Node 的 --jitless 无法工作(它会禁用 WebAssembly)。限制虚拟内存的主机(ulimit -v、vm.overcommit_memory=2)会拒绝需要预留约 22 GB 地址空间的 Node 构建。Node 26 的官方二进制文件在自行安装 tarball 的极简镜像上需要 libatomic1。

Lean 支持与限制

构建强制执行提前(ahead-of-time)执行。 支持普通函数、递归、闭包、归纳类型、模式匹配、类型类、依赖类型和编译后的 IO。导入、宏、 elaboration、tactic、deriving、证明和 #eval 在托管的 native Lean 中在编译期间运行。初始化程序算作运行时依赖项:宽泛的 import Lean 可能会保留编译器;当只有宏或 tactic 需要它时使用 meta import Lean,对于运行时数据库则使用更窄的导入(具有 Lean.Json 的 import Lean,以及 deriving ToJson, FromJson,构建并运行)。每一次拒绝都会有解释:Lasm 会打印从你的代码到编译器代码的链,当起因是宽泛的导入时,还会打印你的代码所使用的更窄的模块。部署的程序会像 native Lean 一样遵循 LEAN_ABORT_ON_NONLINEAR=1。各平台结果:language coverage。

部署的应用程序不能使用:

运行时不可用 示例与确切边界
加载 Lean 模块数据或定位编译器安装 Lean.importModules、Lean.withImportModules、模块数据读写器、Lean.findSysroot、Lean.initSearchPath;已部署的 .olean/IR 加载。
求值或编译新的 Lean 代码 Lean.Environment.evalConst、解释器求值、Lean REPL、运行时 elaboration/编译、按名称加载的声明求值。允许调用普通的已编译函数。
使用 Lean 的编译器/内核运行时状态 运行时 elaboration、内核证明检查、编译器环境、需要 Lean C++ 编译器/内核的语言服务器机制。如果纯 Lean 数据的可达依赖项通过检查,则允许进行纯 Lean 数据操作。LeanExport.parseStream 通过内核构建 Lean.Expr 值,因此会被拒绝。
动态加载可执行插件 Lean/Wasm 插件加载、dlopen/dlsym(调用 dlopen 的 C 代码会获得一个总是失败的实现)、运行时 Lean 符号查找。

构建会检查可达的运行时依赖项,包括导入的库和间接调用;即使您的输入不会走该分支,可达的禁用调用也会被拒绝,并且链接器移除的死代码不计入内。在加载应用程序之前,启动程序还会拒绝丢失、陈旧或不兼容的功能记录(这是一个一致性检查,而不是安全沙箱)。不存在庞大的兼容性回退机制。

Lake 包。仅为编译而导入的模块(例如用于宏的战术、细化器,例如 Aesop、Qq 或 import Lean)不会将 Lean 编译器留在部署中。Lasm 仅在程序使用其定义或注册的内容时,或者当它们是程序自身编写的代码执行 IO 或调用 C 时(--verbose 显示了跳过了多少个),才会运行模块的初始化程序。包捆绑的 C 源代码(extern_lib、moreLinkObjs,例如 leansqlite 的 SQLite)使用 Lean 自己的 clang 进行编译,作为 C 层获取一次(39–52 MB);不需要系统的 C 编译器(macOS 需要用于 C 库头文件的 Xcode Command Line Tools SDK)。无法链接预构建的原生库(共享库、-l 选项:libcurl、OpenSSL、libpq、BLAS);构建会指明库和包的名称。

非发布保证。控制台输出、参数、退出码、本地 Lake 导入以及选定的语言/文件系统测试拥有原生与 Node 的对比测试,并且在 0.1.0 之前,Lean 具备运行时能力的上游套件和 19 个生态系统项目在所有五个平台上运行,与上一个接受的候选版本相比零回归(0.1.0 门禁)。不保证完整的 IO.FS、并发性、子进程/信号/终端奇偶校验、每个第三方库以及完整的主流套件(IO 差距)。大数字(超出 63 位的 Nat/Int)使用 Lean 自己的任意精度代码来代替 GNU MP,因此应用不包含 LGPL 代码;结果与原生 Lean 相同,但在 Wasm 中,在 1,000 位时,乘法比使用 GMP 慢约 5 倍,Nat.gcd 慢约 60 倍(数字)。Lake 依赖项使用您的系统 Git(系统 Git)。

发布版本与来源

0.1.0 是第一个 npm 版本(说明);0.2.0 添加了边缘目标和 Bun/Deno(说明);0.3.0 添加了浏览器、Lasm.UI、全栈应用、WASI/Fastly 和编辑器支持(说明);0.3.1 将启动代码置于 MIT-0 许可证下并添加了错误报告指针(说明);0.3.2 修复了 Std.Internal.UV 套接字、定时器和信号(说明);0.3.3 从未发布,其更改随 0.3.4 发布(说明);0.3.5 更新了 README 和 Conduit 示例(说明)。Lasm 的 npm 包(@lasm/cli、@lasm/create 和 @lasm/… 工具包)仅通过 release.yml 工作流发布,通过带有来源证明的 npm 可信发布:不存在 npm 令牌。一个发布版本是一个提升 package.json 版本的拉取请求(pull request),并且只有在发布提交的 release-checks 状态(五平台候选检查;边缘、Bun/Deno、浏览器、Lasm.UI、WASI/Fastly、全栈、单元和开发循环检查;以及确切包的 npm 排练)通过后才会发布。发现了 Bug?npx lasm --version 提供了bug 报告表单所要求的版本行。npm view @lasm/cli@<version> 显示了来源证明,项目中的 npm audit signatures 可以对其进行验证。详情:RELEASING.md。

许可协议

Lasm 的源码采用 MIT License(版权所有 Jordan Last)。 初始代码——在新建项目中放入的一切 lasm init 和 npm create @lasm、templates/、examples/,以及本 README 和 docs/ 中的代码示例——在所有版本中同样采用 MIT No Attribution (MIT-0):它们完全归你所有,无需署名。@lasm/create 采用 MIT,并且 @lasm/cli 的 license 字段是 Lasm 的 MIT、MIT-0 及其打包的所有组件的 SPDX 表达式,其文本位于 licenses/ 中。许可证审计列出了每个发布的组件、其许可证以及各项义务的履行方式。

  • 构建 dist/。 THIRD_PARTY_NOTICES.txt 以 Lasm 的 MIT 声明以及 Lasm 修改的 Lean 文件列表开头,随后是构建所包含内容的许可证:Lean 的运行时与标准库(Apache-2.0)、Emscripten(MIT OR NCSA)、musl、LLVM libc++、libc++abi、libunwind 和 compiler-rt、mimalloc、libuv、koffi 以及 Lasm 的宿主(MIT)。应用不包含任何 copyleft 代码。licenses/<package>/ 保存了编译进 program.wasm 的所有 Lake 依赖项的许可证文件;通过 npm 互操作,node_modules/ 保存了带有各自许可证的每个软件包。当你分发 dist/ 时,请保留这些文件。
  • Edge、浏览器、WASI、Fastly 和 wasi-http 输出采用相同的声明,经自动重写以说明其文件包含的内容:每个输出目录中的一个 THIRD_PARTY_NOTICES.txt、平台捆绑的 JavaScript 上的简短 /*! … */ 许可证横幅(edge 胶水代码、浏览器加载器)、位于服务器端输出的 Wasm 内部的完整声明文件(一个 lasm.notices 自定义节,因此它会随每次部署一起传输)、Fastly 软件包中的文件,以及 Vite 构建中的 THIRD_PARTY_NOTICES.lasm.txt。这对你的应用意味着什么:docs/LICENSING.md。
  • 工具包与发布归档。每个 @lasm/… 工具包都包含一个 SPDX license 字段和归档的许可证文件。Lean 归档包含的 (L)GPL 部分(GNU MP、GNU C 库、GCC 运行时库、Linux UAPI 头文件、MinGW-w64)以及 Lean 自身源码的具体来源,均作为发布它们的发行版的资产进行镜像(lean-4.35.0-tiers-v2)。 Lasm 不发布任何 Git 和 Apple SDK 文件。
  • Lean 名称和标志是 Lean FRO 的商标。Lasm 与 Lean FRO 无隶属关系,亦未经其背书。

来源:Hacker News-首页 · github.com