展示 HN:使用 TypeScript 和 Express 编写原生二进制 Web 应用
Show HN: Write native binary web apps with TypeScript and Express

原始链接: https://github.com/tsoniclang/express

## @tsonic/express:为 Tsonic 提供 Express 风格的 API `@tsonic/express` 允许开发者使用 TypeScript 构建类似 Express 的 Web 应用程序,并将其编译为原生二进制文件,使用 Tsonic。它为那些有 Node.js Express 框架经验的开发者提供了熟悉的 API。 **主要特性包括:** * **兼容 Express 的 API:** 提供 `app.get`、`app.post`、`app.put` 等方法和中间件函数 (`app.use`)。 * **任务优先的处理程序:** 路由处理程序和中间件*必须*是异步函数,确保可预测的执行和错误处理。它们遵循一致的 `(req, res, next)` 签名。 * **请求和响应对象:** 提供对请求详情(方法、路径、查询参数、主体、cookie)和响应方法(状态码、发送数据、重定向、设置头部/cookie)的访问。 * **内置中间件:** 包括对 JSON、URL 编码、文本、原始主体解析和文件上传的支持。 * **静态文件服务:** 使用 `express.static` 轻松提供静态资源。 **入门:** 初始化一个 Tsonic 项目,将 `@tsonic/express` 添加为依赖项,并在 `App.ts` 文件中定义路由。提供了一个简单的“hello world”示例,以便快速设置。

Hacker News新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交登录展示 HN:用 TypeScript 和 Express 编写原生二进制 Web 应用 (github.com/tsoniclang)3 分,作者 jeswin 2 小时前 | 隐藏 | 过去 | 收藏 | 1 条评论帮助 orta 0 分钟前 [–] 有趣的项目!已将其添加到我的 TypeScript 衍生语言列表中:https://github.com/orta/awesome-typescript-derived-languages回复 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文

Express-style HTTP server APIs for Tsonic.

This package is part of Tsonic: https://tsonic.org.

Use this package to write Express-like apps in TypeScript and compile them to native binaries with tsonic.

Quick Start (new project)

mkdir my-api && cd my-api
npx --yes tsonic@latest init

# Install Express runtime + bindings (installs required ASP.NET Core deps too)
npx --yes tsonic@latest add npm @tsonic/express

# Replace the default App.ts with a minimal API
cat > packages/my-api/src/App.ts <<'EOF'
import { express } from "@tsonic/express/index.js";

export function main(): void {
  const app = express.create();

  app.get("/", async (_req, res, _next) => {
    res.json({ ok: true });
  });

  app.listen(3000);
}
EOF

npm run dev

Then open http://localhost:3000/.

// packages/my-api/src/App.ts
import { express } from "@tsonic/express/index.js";

export function main(): void {
  const app = express.create();

  app.get("/", async (_req, res, _next) => {
    res.send("hello");
  });

  app.listen(3000);
}

Handler model (important)

This package is Task-first (like ASP.NET): route handlers and middleware should be written as async functions (even if you don't await anything).

This avoids “async-void” behavior and keeps execution/exception semantics deterministic.

Also, handlers use the 3-argument signature: (req, res, next) (even for routes). If you don't need next, name it _next.

import { express } from "@tsonic/express/index.js";

const app = express.create();
const router = express.Router();

router.get("/ping", async (_req, res, _next) => {
  res.send("pong");
});

app.use("/api", router);

Common verbs:

app.get("/health", async (_req, res, _next) => {
  res.send("ok");
});
app.post("/items", async (req, res, _next) => {
  res.json(req.body);
});
app.put("/items/:id", async (req, res, _next) => {
  res.send(req.params["id"] ?? "");
});
app.delete("/items/:id", async (_req, res, _next) => {
  res.sendStatus(204);
});
app.patch("/items/:id", async (_req, res, _next) => {
  res.sendStatus(204);
});
app.all("/anything", async (_req, res, _next) => {
  res.send("matched");
});
app.use(async (req, _res, next) => {
  // Do something with req
  await next();
});
app.get("/set-cookie", async (_req, res, _next) => {
  res.cookie("sid", "abc");
  res.send("ok");
});

app.get("/read-cookie", async (req, res, _next) => {
  res.json({ sid: req.cookies["sid"] });
});

Error middleware:

app.useError(async (err, _req, res, _next) => {
  res.status(500).json({ error: `${err}` });
});

Request highlights:

  • req.method, req.path, req.originalUrl
  • req.query, req.params, req.cookies, req.signedCookies
  • req.body (when using body parsers)
  • req.get(name) / req.header(name)

Response highlights:

  • res.status(code)
  • res.send(body), res.json(body), res.sendStatus(code)
  • res.redirect(path) / res.redirect(status, path)
  • res.set(name, value) / res.header(name, value)
  • res.cookie(name, value, options) / res.clearCookie(name, options)
app.use(express.json());
app.use(express.urlencoded());
app.use(express.text());
app.use(express.raw());
const upload = express.multipart();

app.post("/upload", upload.single("avatar"), async (req, res, _next) => {
  res.json({
    filename: req.file?.originalname,
    fields: req.body,
  });
});
app.use(express.static("./public"));
const server = app.listen(3000);
server.close();

This repo is versioned by runtime major:

MIT

联系我们 contact @ memedata.com