跳转至内容
There is a version suitable for your browser's language settings. Would you like to go to the english language of the site?
主页文档

API 接口

H1

API 接口

/src/apps 是一个“魔法”目录,任何带有 api 导出的代码都会自动地注册为路由。在这里,你可以自由地创建任何所需的目录结构,尽情编写代码。

尝试和世界打个招呼,很简单吧?

/src/apps/hello-world/say.ts
/**
* 这是一个向世界问好的 API!
* 这些 ~~注释~~ 将在 **Cookbook** 中展示。
*/
export const api = defineApi({
meta: {},
async action(params: string & typia.tags.MinLength<2> & typia.tags.MaxLength<16>, context) {
return `你好世界! (来自 ${params})`
},
});

API 定义的方式和编写普通函数非常类似。action 是 API 执行的实际操作,你可以返回任何内容,无论是字符串、对象还是数组,它们最终都会被自动转换为 JSON(确切地说是 TSON)。注意,文件中只能导出一个 API,且名称必须是 api

你可能对 metaparamscontext 的作用感到好奇。以下内容将为你解答这些问题。

元数据(Meta)

请稍等片刻,待你熟悉了 Milkio 之后,可以翻阅元数据章节来了解其详细信息。

参数(Params)

params 决定 API 可以接收哪些输入。Milkio 会自动利用 Typia 来确保接收到的参数类型正确。不符合预期的数据类型或多余属性将被拒绝,从而实现了“类型安全”的魔法。

对于你而言,只需编写纯粹的 TypeScript 类型,你可以随意使用泛型和任何高级 TypeScript 特性。

/src/apps/hello-world/say.ts
action(
params: { id: string; gender: string; email: string; age: number; },
context
) {

Typia 的亮点之一是支持类型标签,你可以用来进一步增强 params 类型。

id: string & typia.tags.Format<"uuid">
gender: "male" | "female" | "other"
email: string & typia.tags.Format<"email">
age: number & typia.tags.ExclusiveMinimum<19> & typia.tags.Maximum<100>

这样,你可以轻松地限制字符串长度、验证是否是有效的电子邮件地址等。

你可能会疑惑,TypeScript 类型在编译为 JavaScript 时会被移除,运行时代码是无类型的。Typia 如何实现这样的“魔法”?

Typia 会分析代码并执行 AOT 编译,将验证部分的代码转换为适合你类型的最佳代码。这使得编写参数类型更加简单,并且运行速度更快。你可以阅读 Typia 的 AOT Compilation 章节来获取更详细的信息。

由于 Milkio 在生成阶段中内置了对 Typia 的支持,因此你可以自由选择任何你喜欢的运行时和打包工具,而无需固定使用 TSC 作为打包工具。

常见的 Typia 类型标签

匹配正则表达式:

string & typia.tags.Pattern<"^[a-z]+$">

限制字符串长度:

string & typia.tags.MinLength<19> & typia.tags.MaxLength<3>

限制数组工程数:

Array<string> & typia.tags.MinItems<3> & typia.tags.MaxItems<10>

上下文(Context)

context 是一个对象,它包含了与当前请求相关的信息和一些有用的方法。在不同的请求之间,context 是独立的实例。

/src/apps/hello-world/say.ts
action(
params: { ... },
context
) {

你可能想知道 context 的具体用途是什么?我们最常接触到的可能是 context.logger,它类似于 console,可以记录运行时的关键信息,便于调试和排错。记录当前请求的日志就像这样:

context.logger.log("Hello, Milkio!")

logger 的用法几乎与 console 相同,你可以阅读 日志 章节来了解更多信息。

context 中,还可以获取到 header。header 是客户端、浏览器和云服务提供商向我们传递额外数据的方式。

例如,浏览器会告诉我们用户使用的系统类型,Vercel 会告诉我们用户所在的城市等。此外,我们通常也会将用户的 token 等信息通过 header 传递给服务器。

export const api = defineApi({
meta: {},
async action(params: undefined, context) {
const city = context.headers.get("X-Vercel-IP-City")
return `您可能位于这个城市: ${city}`
},
});

注意,上面的 header 并不是一个常规的 HTTP header,而是由 Vercel 提供的。因此,除非你的代码已经部署在 Vercel 上,否则你可能无法直接运行这段代码。

URL

contextdetail 中,我们还可以获取当前请求的 URL 对象。

注意,对于 detail 中的数据,只有在 HTTP 方式调用时才存在。这意味着在测试时,这些值将不会出现。

export const api = defineApi({
meta: {},
async action(params: undefined, context) {
const fullurl = context.detail.fullurl!
return `您的完整URL: ${fullurl.toString()} 您的路径: ${fullurl.pathname}`
},
});

URL Params

我们还可以获取 URL Params,即 URL 中 ? 之后的字符串。

终端窗口
http://example.com/foo?name=bar&topic=api
export const api = defineApi({
meta: {},
async action(params: undefined, context) {
const fullurl = context.detail.fullurl!
return `从 URL Params 获取的名字: ${fullurl.searchParams.get("name")}` // bar
},
});

更多

除此之外,context 还有很多其他用途,你可以等到熟悉 Milkio 后,阅读 上下文 章节来进一步了解。