milkio 0.7.0-alpha.9 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "enableReleases": true,
3
+ "githubOwner": "akirarika",
4
+ "githubRepo": "milkio",
5
+ "giteeOwner": "akirarika",
6
+ "giteeRepo": "milkio"
7
+ }
File without changes
@@ -0,0 +1,13 @@
1
+ # 0.1.0 - 序幕
2
+
3
+ > 世界终末之时,黑川想起了第一次见到爱丽丝时的样子。那时,黑川正走在东京都最繁华的街道旁,一个少女脏兮兮地坐在那里。抱着膝盖,眼神充满了迷茫和无助,仿佛是一只孤独的小猫,被世界给遗弃。
4
+
5
+ ## 生日快乐
6
+
7
+ 这是 Milkio 的第一个版本!
8
+
9
+ 实际上,在发布之前,我已经花了接近一年的时间来打磨它。所以,尽管刚刚发布,Milkio 的完成度却很高,有好看的文档和完善的工具。希望大家能够喜欢它!
10
+
11
+ 你可能在疑惑,开头的这段话是什么,许多开源的项目都喜欢为每个版本都起一些比较中二病的名字,我觉得这种传统非常有趣!我想拿小说的章节,作为版本的名称,并把其中的段落作为发行说明的开篇。小说本身是虚构的,段落也是我自己编纂出来的,但如果有机会,我可能会把它写成一部真正的小说并发行(只是想想而已啦)。
12
+
13
+ 总之!希望你喜欢 Milkio!
@@ -0,0 +1,33 @@
1
+ # 0.2.0 - 初遇
2
+
3
+ > 电视机正报道着新闻,爱丽丝就是从实验室中失控逃出的超能力者。黑川暗自腹诽,自己究竟给自己找了多大的麻烦,竟然因为可怜,把她带回了家。她好像失忆了,对自己的之前的经历毫不知情,只会缠在黑川身边,踮着脚尖拉着黑川的衣袖说,我饿了。
4
+
5
+ ## 命令
6
+
7
+ 现在,Milkio 还可以用来开发一些使用终端运行的小工具![文档](https://milkio.fun/essentials/command)
8
+
9
+ 位于 `/apps/$/` 目录下的任何 API 都会被当做是命令。对于命令,使用起来就像是普通的 API,不同的是参数的格式。
10
+
11
+ 你现在拥有 `commands` 和 `options` 两个参数。这两个参数由 Milkio 帮你从 argv 中自动解析而来。看一下下面的例子,分别是执行的命令,和获取到的 params。
12
+
13
+ ```bash
14
+ ./app say hello world --foo=bar --enable
15
+ ```
16
+
17
+ ```ts
18
+ params: {
19
+ commands: ["hello", "world"],
20
+ options: {
21
+ foo: "bar",
22
+ enable: true,
23
+ },
24
+ }
25
+ ```
26
+
27
+ 想要了解更多的用法,请阅读 [文档](https://milkio.fun/essentials/command)!
28
+
29
+ ## 升级
30
+
31
+ ```
32
+ bun i milkio@0.2.0
33
+ ```
@@ -0,0 +1,85 @@
1
+ # 0.3.0 - 游乐园
2
+
3
+ > “很简单呀,只要我想象着冰淇凌在我手里就好了呀。”爱丽丝边舔冰淇凌边说,“不过…… 之后就会逐渐变得很累,会困得直接睡着。而且只有清楚记得细节的东西才可以,逃出来的时候,我想要变出一顶帽子遮住自己的脸,却变出了一只吞掉大象的蛇,可怕。”
4
+
5
+ ## 全新的创建工具
6
+
7
+ 现在,Milkio 提供了一个工具,来帮助你方便地创建新工程。
8
+
9
+ ```bash
10
+ bun create milkio
11
+ ```
12
+
13
+ 只要运行命令并回答一系列问题,你就可以得到一个全新的 Milkio 工程。
14
+
15
+ ## Windows 支持
16
+
17
+ Bun 已经完成了对 Windows 平台的正式支持,经过一系列的调整,现在 Milkio 也支持在 Windows 平台上使用了。
18
+
19
+ ## 对 Stream API (Server-Sent Events) 的支持
20
+
21
+ 文档:[Stream](https://milkio.fun/essentials/stream)
22
+
23
+ 现在 Milkio 支持了以流的方式发送 API 响应。当你的应用包括和大语言模型聊天,或者当他人评论你的博客时需要实时提醒时,这将很有用。
24
+
25
+ ```ts
26
+ export const api = defineApi({
27
+ meta: {},
28
+ action: async function* (params: undefined, context) {
29
+ yield "hello";
30
+ yield "world";
31
+ },
32
+ });
33
+ ```
34
+
35
+ ## 客户端包现在基于 Fetch
36
+
37
+ 客户端包现在会默认使用 Fetch。以前,你需要手动通过 `handler` 告诉客户端包如何发送请求,如何存储数据:
38
+
39
+ ```ts
40
+ import { createClient } from "client";
41
+
42
+ export const client = createClient({
43
+ baseUrl: "http://localhost:9000/",
44
+ storage: localStorage,
45
+ async handler(url, body, headers) {
46
+ return await (await fetch(url, { method: "POST", body, headers })).text();
47
+ },
48
+ });
49
+ ```
50
+
51
+ 现在,默认情况下,客户端包会使用 Fetch 来发送请求,并使用 `localStorage` 来存储数据。
52
+
53
+ ```ts
54
+ import { createClient } from "client";
55
+
56
+ export const client = createClient({
57
+ baseUrl: "http://localhost:9000/",
58
+ });
59
+ ```
60
+
61
+ 某些环境下,或许缺少一些所需的对象,你可以在选项中提供 `storage`、`fetch`、`abort` 这些的 polyfill。其中对于 `storage`,甚至支持异步的。
62
+
63
+ ## 静态服务器
64
+
65
+ 文档:[Static](https://milkio.fun/extensions/static)
66
+
67
+ Milkio 现在支持静态服务器,这意味着你可以将前端打包出的静态资产与 Milkio 一起部署。
68
+
69
+ ## VS Code 菜单栏
70
+
71
+ 文档:[VS Code Menubar](https://milkio.fun/extensions/menubar)
72
+
73
+ 现在,你可以自由配置 Milkio 的 VS Code 菜单栏。你可以将自己常用的脚本放在菜单栏中,这样不用手动输入命令,也可以快速调用。
74
+
75
+ ## Drizzle
76
+
77
+ 文档:[Drizzle](https://milkio.fun/drizzle/getting-started)
78
+
79
+ 现在,Drizzle 是 Milkio 首选的 ORM,它是唯一同时具有关系型查询 API 和类似 SQL 查询 API 的 ORM,在访问关系数据时为您提供两全其美的服务。
80
+
81
+ 尽管 Drizzle 在使用上或许有些繁琐,但 Milkio 提供了一系列功能,来帮助你简化 Drizzle 的使用。Milkio 的 Drizzle 相关文档是从零 SQL 基础的角度去编写的,在此前没有 SQL 经验的使用者,也能够快速通过文档来入门。
82
+
83
+ ## 优化生成阶段性能
84
+
85
+ 在过去,生成阶段通过加载一遍 TypeScript 文件的方式来获取 API 的信息,现在,改为了直接以字符串的形式分析 TypeScript 文件本身。
@@ -0,0 +1,35 @@
1
+ # 0.4.0 - 匿名通话
2
+
3
+ > “七十五万円,对于你一个大学生来说,已经够多了吧。”电话那端传来冰冷的机械音,显然是为了避免泄露讲话者的身份,“虽然我不知道为什么她在你身边就会安静下来,但这也免得我们大费周章了。把她带到整个东京最高的地方,天空树的顶层。高空是天然的屏障,那里就是她的鸟笼。把她带到这里,等待到夜间 10 点整,找个理由悄悄离开就好了,我们会处理剩下的事。”
4
+
5
+ ## 🚨 破坏性的用法更改:execute 相关方法
6
+
7
+ > 我们会努力保持用法的兼容性,但在 Milkio 的 1.0 版本发布之前,可能会有一些破坏性的用法更改。
8
+
9
+ 此前,execute 相关方法的用法是这样的:
10
+
11
+ ```ts
12
+ app.execute('foo/bar/baz', 'some-params', { 'Content-Type': 'application/json' }, { ... })
13
+ ```
14
+
15
+ 现在,参数改为了类似 fetch 的用法:
16
+
17
+ ```ts
18
+ app.execute('foo/bar/baz', {
19
+ params: 'some-params',
20
+ headers: { 'Content-Type': 'application/json' },
21
+ ...
22
+ })
23
+ ```
24
+
25
+ ## 更好的失败类型
26
+
27
+ 现在,Milkio Client 在 `TYPE_SAFE_ERROR` 失败的返回值的类型更加准确,我们甚至可以利用编辑器自动补全诸如 `foo.fail.data.path === "$input.password"` 这样的代码,是的,`"$input.password"` 这种字符串,也能够被补全和检查出错误。
28
+
29
+ 更新命令:`cd ./packages/client && bun i milkio-client@0.4.0`
30
+
31
+ ## 升级
32
+
33
+ ```
34
+ bun i milkio@0.4.0
35
+ ```
@@ -0,0 +1,19 @@
1
+ # 0.5.0 - 天空树
2
+
3
+ > 金色的夕阳逐渐从城市中褪去,街灯和招牌陆陆续续地亮起,在天空树上俯瞰,整个东京就像逐渐亮起的星空一样,繁华而璀璨,“只有你会给我买冰淇淋,”爱丽丝紧紧扯着黑川的衣袖,好像下一秒就会失去他似的,“会陪着我,很温柔,而且…从不把我当作怪物看,我…也许喜欢上你了!”
4
+
5
+ ## 测试
6
+
7
+ 在这个版本中,Milkio 主要进行了测试相关功能的改进
8
+
9
+ - 现在测试拥有颜色的漂亮输出
10
+
11
+ - 以前,遇到失败时测试将终止,现在不会终止,而是进行完所有的测试
12
+
13
+ - 对于 Stream 来说,测试失败时,不会卡住而是会被正常认为是失败的
14
+
15
+ ## 升级
16
+
17
+ ```
18
+ bun i milkio@0.5.0
19
+ ```
@@ -0,0 +1,41 @@
1
+ # 0.6.0 - 正常的世界
2
+
3
+ > 爱丽丝的求救声回响在黑川的耳畔,黑川装作什么也听不见,步入电梯,如同一尊麻木的雕像。电梯缓缓下降,楼层一个接一个地掠过,爱丽丝的呼声逐渐被电梯播放的旋律所淹没,如同雨滴融入大海,尽管最初泛起细微的波纹,最终却归于沉寂。“欢迎回到现实世界,”黑川对自己说,声音中带着不易察觉的颤抖,“一个超能力只存在于幻想小说中的世界。”
4
+
5
+ ## Electron
6
+
7
+ 现在,Milkio 可以用来创建桌面应用了,并且可以打包成 macOS、Windows、Linux 三个平台下的应用
8
+
9
+ 这是使用 Electron 完成的,Electron 的主进程和渲染进程之间的通信很麻烦,通过引入 Milkio,很好地解决了这个问题
10
+
11
+ 对于前端而言,我们默认为你安装了 [Astro](https://astro.build/),它一个支持主流的前端框架(如 Vue3、React、Svelte 等),并且默认会进行 SSG,这可以让你的应用运行速度更快
12
+
13
+ 你可以通过运行 `bun create milkio` 后,选择 `electron (alpha)` 模板进行体验
14
+
15
+ 不过你需要注意,这仍然处于 alpha 阶段,可能会有许多问题,未来也可能进行不兼容的改动
16
+
17
+ ## Node
18
+
19
+ 对于一些担忧 Bun 稳定性的用户,现在你可以使用 Node.js 来创建 Milkio 应用了
20
+
21
+ 无论是在本机上开发,还是运行测试,都是使用 Node.js 完成的,不过,你在开发时,仍然需要 Bun,因为 Milkio 依赖 Bun,在你开发时完成自动生成以及许多辅助操作
22
+
23
+ 你可以通过运行 `bun create milkio` 后,选择 `node (beta)` 模板进行体验
24
+
25
+ ## VS Code 模板
26
+
27
+ 修复了在 Windows 下的兼容性问题,现在 Windows 下也可以正常工作了
28
+
29
+ ## 客户端
30
+
31
+ 修复了在 Windows 下,客户端类型不会自动更新的问题,现在 Windows 下也可以正常工作了
32
+
33
+ ## 性能改进
34
+
35
+ 现在在 Windows 下,Milkio 的启动速度变得非常快
36
+
37
+ ## 升级
38
+
39
+ ```
40
+ bun i milkio@0.6.0
41
+ ```
@@ -0,0 +1,128 @@
1
+ # 0.7.0 - 某章节名
2
+
3
+ > 黑川讨厌自己,讨厌那个因为害怕而当胆小鬼的自己。
4
+ > 爱丽丝把自己当做了唯一,是他,带她见到了这个色彩斑斓的世界,却又在短短数天后把她给抛弃。
5
+ > 黑川只要一闭上眼睛,脑海中就浮现出爱丽丝依偎在自己手臂的画面,笑的那么开心,嘴角还残留着冰淇淋的痕迹。
6
+ > 终于,黑川颤抖着手臂,按下了通往顶层的电梯按钮。
7
+ > “不管怎样…我不会抛弃你的…” 黑川深呼吸,随着电梯门缓缓打开,他的眼神逐渐坚定如钢铁。
8
+
9
+ ## 功能:Milkio Steps
10
+
11
+ Milkio 中,新增了一种编写 API 的心智模型:Steps。它可以让你将很长的 API 代码拆分为若干个小的步骤,这对于复杂的 API 代码编写,可以提升代码的可读性。
12
+
13
+ ```ts
14
+ async action(
15
+ params: {
16
+ by: string & typia.tags.MinLength<2> & typia.tags.MaxLength<16>;
17
+ },
18
+ context,
19
+ ) {
20
+ const result = await context
21
+ /**
22
+ * Step 1
23
+ */
24
+ .step(async (stages) => {
25
+ const message1 = `Step 1`;
26
+
27
+ return { message1 };
28
+ })
29
+ /**
30
+ * Step 2
31
+ */
32
+ .step(async (stage) => {
33
+ const $message2 = `Step 2`;
34
+
35
+ return { $message2 };
36
+ })
37
+ /**
38
+ * Step 3
39
+ */
40
+ .step(async (stage) => {
41
+ if (!stage.message1) throw reject("INTERNAL_SERVER_ERROR", undefined);
42
+ if (!stage.$message2) throw reject("INTERNAL_SERVER_ERROR", undefined);
43
+ return {};
44
+ })
45
+ .run();
46
+
47
+ return result;
48
+ }
49
+ ```
50
+
51
+ 其中,每个 `step` 都是一个函数,返回一个对象,这个对象会被合并到下一步的 `stage` 中。
52
+
53
+ 如果对象中的属性是以 `$` 开头的,那么 Milkio 会将其视为一个私有属性,尽管在 `stage` 中它始终可访问,但在 `result` 中,它会被移除。
54
+
55
+ 为了避免对 `stage` 中的属性进行修改,从而导致难以知晓某些值在哪一步被更改,被属性设计为是不可变的。
56
+
57
+ ## VS Code:Milkio Structure
58
+
59
+ > 注意:需要将 Milkio 的 VS Code Extension 更新到最新
60
+
61
+ 现在,你的 VS Code 资源管理器底部会显示你 Milkio API 的结构。你可以通过它定位较长的 API 代码。
62
+
63
+ ```ts
64
+ ⬇️ Meta
65
+ ⬇️ Action
66
+ step: Step 1
67
+ step: Step 2
68
+ step: Step 3
69
+ ⬇️ Tests
70
+ test: Basic
71
+ ```
72
+
73
+ ## VS Code:同时启动前端工程
74
+
75
+ > 注意:需要将 Milkio 的 VS Code Extension 更新到最新
76
+
77
+ 现在,Milkio 支持关联你的前端工程了,并且在启动 Milkio 时,同步启动它们。在 `milkio.toml` 中像下面这样配置即可。
78
+
79
+ ```toml
80
+ [link]
81
+ projects = [
82
+ { name = 'YourViteProject', cwd = '../your-project-path', script = 'bun run dev' },
83
+ ]
84
+ ```
85
+
86
+ ## VS Code:工作区优化
87
+
88
+ > 注意:需要将 Milkio 的 VS Code Extension 更新到最新
89
+
90
+ 以前,当使用工作区时,只有当前在屏幕上所打开的文件,位于一个 Milkio 工程中时,Milkio 的菜单栏才会出现。
91
+
92
+ 这是因为,我们通过当前屏幕上所打开的文件,来判断这个工程是否是一个 Milkio 工程,以及你想要操作哪个 Milkio 工程。
93
+
94
+ 现在,当工作区中,只有一个是 Milkio 工程时,Milkio 的菜单栏会始终出现,我们假定你要操作的,就是这个 Milkio 工程。
95
+
96
+ ## 配置:根据环境自动切换
97
+
98
+ 现在,配置支持根据不同的环境来自动读取不同的配置了。
99
+
100
+ https://milkio.fun/essentials/config
101
+
102
+ ## 测试:支持使用真实请求测试
103
+
104
+ 现在,测试新增了 `client` 对象,你可以利用它,使用真实的客户端包,发送真实的请求。
105
+
106
+ https://milkio.fun/essentials/api-test
107
+
108
+ ## 模板:支持 Cloudflare Workers
109
+
110
+ 现在,Milkio 完成了对 Cloudflare Workers 的支持,你可以通过 `bun create milkio` 时间选择 `cloudflare` 选项,来创建一个 Cloudflare Workers 项目。
111
+
112
+ ## 文档:运行时文档改进
113
+
114
+ 现在,我为每个运行时都编写了文档,在其中讲述了注意事项和如何部署。
115
+
116
+ Bun: https://milkio.fun/runtime/bun/
117
+ Node.js: https://milkio.fun/runtime/node/
118
+ Cloudflare: https://milkio.fun/runtime/cloudflare/
119
+ Electron: https://milkio.fun/runtime/electron/
120
+
121
+ ## 升级
122
+
123
+ 使用新版本时,请务必也一同升级你的客户端包的版本。
124
+
125
+ ```
126
+ bun i milkio@0.7.0
127
+ cd packages/client && bun i milkio-client
128
+ ```
File without changes
@@ -0,0 +1,13 @@
1
+ # 0.1.0 - Prologue
2
+
3
+ > At the end of the world, Kurokawa remembered the first time he saw Alice. At that time, Kurokawa was walking along the busiest street in Tokyo, where a girl was sitting there, dirty and disheveled. Hugging her knees, her eyes were filled with confusion and helplessness, as if she were a lonely kitten, abandoned by the world.
4
+
5
+ ## Happy Birthday
6
+
7
+ This is the first version of Milkio!
8
+
9
+ In fact, before the release, I have spent nearly a year polishing it. So, despite being just released, Milkio is quite complete, with beautiful documentation and comprehensive tools. I hope you like it!
10
+
11
+ You might be wondering what the opening paragraph is about. Many open-source projects like to give each version a somewhat melodramatic name, and I find this tradition quite interesting! I wanted to use chapters of a novel as version names, and use paragraphs from the novel as the opening of the release notes. The novel itself is fictional, and the paragraphs are also fabricated by me, but if given the chance, I might turn it into a real novel and publish it (just a thought).
12
+
13
+ Anyway! I hope you like Milkio!
@@ -0,0 +1,33 @@
1
+ # 0.2.0 - First Encounter
2
+
3
+ > The television was reporting the news, and Alice was the superpowered individual who had escaped from the lab. Kurokawa muttered to himself, wondering what kind of trouble he had gotten himself into by taking pity on her and bringing her home. She may have lost her memory, having no knowledge of her past experiences, and would only cling to Kurokawa, tugging at his sleeve and saying, "I'm hungry."
4
+
5
+ ## Commands
6
+
7
+ Now, Milkio can also be used to develop small tools that run in the terminal! [Documentation](https://milkio.fun/essentials/command)
8
+
9
+ At `/apps/$/` directory will be treated as a command. For commands, usage is similar to regular APIs, with the exception of the parameter format.
10
+
11
+ You now have two parameters: `commands` and `options`. These parameters are automatically parsed by Milkio from `argv`. Take a look at the examples below, which show the executed command and the obtained `params`.
12
+
13
+ ```bash
14
+ ./app say hello world --foo=bar --enable
15
+ ```
16
+
17
+ ```ts
18
+ params: {
19
+ commands: ["hello", "world"],
20
+ options: {
21
+ foo: "bar",
22
+ enable: true,
23
+ },
24
+ }
25
+ ```
26
+
27
+ To learn more about usage, please read the [documentation](https://milkio.fun/essentials/command)
28
+
29
+ ## Upgrade
30
+
31
+ ```
32
+ bun i milkio@0.2.0
33
+ ```
@@ -0,0 +1,85 @@
1
+ # 0.3.0 - Amusement Park
2
+
3
+ > "It's simple, just imagine the ice cream in my hand," Alice said while licking her ice cream, "but... it gets very tiring after a while, and I'll fall asleep right away. And it only works for things I remember in detail. When I tried to escape, I wanted to create a hat to cover my face, but instead, I created a snake that swallowed an elephant. Scary."
4
+
5
+ ## Brand New Creation Tool
6
+
7
+ Now, Milkio offers a tool to help you create new projects easily.
8
+
9
+ ```bash
10
+ bun create milkio
11
+ ```
12
+
13
+ By running the command and answering a series of questions, you can get a brand new Milkio project.
14
+
15
+ ## Windows Support
16
+
17
+ Bun has officially completed support for the Windows platform. After a series of adjustments, Milkio now supports the Windows platform as well.
18
+
19
+ ## Support for Stream API (Server-Sent Events)
20
+
21
+ Documentation: [Stream](https://milkio.fun/essentials/stream)
22
+
23
+ Now Milkio supports sending API responses in a streaming manner. This will be useful when your application includes chatting with a large language model or when you need real-time notifications when someone comments on your blog.
24
+
25
+ ```ts
26
+ export const api = defineApi({
27
+ meta: {},
28
+ action: async function* (params: undefined, context) {
29
+ yield "hello";
30
+ yield "world";
31
+ },
32
+ });
33
+ ```
34
+
35
+ ## Client Package Now Based on Fetch
36
+
37
+ The client package now defaults to using Fetch. Previously, you had to manually tell the client package how to send requests and how to store data through the `handler`:
38
+
39
+ ```ts
40
+ import { createClient } from "client";
41
+
42
+ export const client = createClient({
43
+ baseUrl: "http://localhost:9000/",
44
+ storage: localStorage,
45
+ async handler(url, body, headers) {
46
+ return await (await fetch(url, { method: "POST", body, headers })).text();
47
+ },
48
+ });
49
+ ```
50
+
51
+ Now, by default, the client package will use Fetch to send requests and `localStorage` to store data.
52
+
53
+ ```ts
54
+ import { createClient } from "client";
55
+
56
+ export const client = createClient({
57
+ baseUrl: "http://localhost:9000/",
58
+ });
59
+ ```
60
+
61
+ In some environments, you might be missing some required objects. You can provide polyfills for `storage`, `fetch`, and `abort` in the options. For `storage`, it even supports asynchronous operations.
62
+
63
+ ## Static Server
64
+
65
+ Documentation: [Static](https://milkio.fun/extensions/static)
66
+
67
+ Milkio now supports a static server, which means you can deploy the static assets packaged by the frontend with Milkio.
68
+
69
+ ## VS Code Menubar
70
+
71
+ Documentation: [VS Code Menubar](https://milkio.fun/extensions/menubar)
72
+
73
+ Now, you can freely configure the VS Code menubar for Milkio. You can place your frequently used scripts in the menubar, so you don't have to manually enter commands and can call them quickly.
74
+
75
+ ## Drizzle
76
+
77
+ Documentation: [Drizzle](https://milkio.fun/drizzle/getting-started)
78
+
79
+ Now, Drizzle is Milkio's preferred ORM. It is the only ORM that has both a relational query API and a SQL-like query API, providing a comprehensive service when accessing relational data.
80
+
81
+ Although Drizzle might be a bit cumbersome to use, Milkio provides a series of features to simplify the use of Drizzle. The documentation for Milkio's Drizzle is written from the perspective of someone with zero SQL knowledge, allowing even those without SQL experience to quickly get started through the documentation.
82
+
83
+ ## Optimizing Generate Phase Performance
84
+
85
+ In the past, the generate phase would load TypeScript files to obtain information about the API. Now, it has been changed to directly analyze the TypeScript files as strings.
@@ -0,0 +1,35 @@
1
+ # 0.4.0 - Anonymous Call
2
+
3
+ > "Seventy-five thousand yen, for a university student like you, should be enough." A cold mechanical voice came from the phone, apparently to avoid revealing the speaker's identity. "Although I don't know why she calms down when she's with you, it saves us a lot of trouble. Take her to the top of Tokyo Skytree, the highest place in the whole of Tokyo. The high altitude is a natural barrier, that's her cage. Bring her here, wait until exactly 10 o'clock at night, find a reason to quietly leave, and we will take care of the rest."
4
+
5
+ ## 🚨 Destructive Usage Changes: execute Related Methods
6
+
7
+ > We will strive to maintain compatibility, but there may be some destructive usage changes before the 1.0 version of Milkio is released.
8
+
9
+ Previously, the usage of execute-related methods was as follows:
10
+
11
+ ```ts
12
+ app.execute('foo/bar/baz', 'some-params', { 'Content-Type': 'application/json' }, { ... })
13
+ ```
14
+
15
+ Now, the parameters have been changed to a fetch-like usage:
16
+
17
+ ```ts
18
+ app.execute('foo/bar/baz', {
19
+ params: 'some-params',
20
+ headers: { 'Content-Type': 'application/json' },
21
+ ...
22
+ })
23
+ ```
24
+
25
+ ## Improved Failure Types
26
+
27
+ Now, the `TYPE_SAFE_ERROR` failure return value type in Milkio Client is more accurate, and we can even use editor auto-completion for code like `foo.fail.data.path === "$input.password"`. Yes, strings like `"$input.password"` can also be auto-completed and errors can be detected.
28
+
29
+ Update command: `cd ./packages/client && bun i milkio-client@0.4.0`
30
+
31
+ ## Upgrade
32
+
33
+ ```
34
+ bun i milkio@0.4.0
35
+ ```
@@ -0,0 +1,19 @@
1
+ # 0.5.0 - Sky Tree
2
+
3
+ > The golden sunset gradually fades from the city, street lights and signs are lit up one after another. Gazing down from the Sky Tree, the entire Tokyo looks like a gradually brightening starry sky, bustling and dazzling. "Only you would buy me ice cream," Alice clings tightly to Kurokawa's sleeve, as if she might lose him at any moment, "you would stay with me, be gentle, and... never treat me like a monster. I... might have fallen for you!"
4
+
5
+ ## Testing
6
+
7
+ Milkio has primarily improved its testing procedures:
8
+
9
+ - Tests now have colorful, attractive output
10
+
11
+ - Previously, tests would terminate upon encountering a failure; now they will not, and will instead complete all tests
12
+
13
+ - For streams, when a test fails, it will not hang but will be correctly identified as a failure
14
+
15
+ ## Upgrade
16
+
17
+ ```
18
+ bun i milkio@0.5.0
19
+ ```
@@ -0,0 +1,41 @@
1
+ # 0.6.0 - A Normal World
2
+
3
+ > Alice's cries for help echoed in Kurokawa's ears, but he pretended not to hear, stepping into the elevator like a numb statue. The elevator descended slowly, floors passing one by one, and Alice's voice was gradually drowned out by the melody playing inside the elevator, like raindrops merging into the ocean, creating faint ripples at first, but ultimately falling silent. "Welcome back to the real world," Kurokawa said to himself, his voice trembling slightly, "a world where superpowers only exist in fantasy novels."
4
+
5
+ ## Electron
6
+
7
+ Now, Milkio can be used to create desktop applications and can be packaged into applications for macOS, Windows, and Linux platforms.
8
+
9
+ This has been achieved using Electron, and the communication between the main process and the rendering process in Electron can be quite troublesome. By introducing Milkio, this issue has been effectively resolved.
10
+
11
+ For front-end developers, we assume that you have installed [Astro](https://astro.build/), which supports mainstream front-end frameworks (such as Vue3, React, Svelte, etc.), and defaults to SSG, which can make your application run faster.
12
+
13
+ You can experience this by running `bun create milkio` and choosing the `electron (alpha)` template.
14
+
15
+ However, please note that this is still in the alpha stage, and there may be many issues. Future updates may also include incompatible changes.
16
+
17
+ ## Node
18
+
19
+ For users concerned about the stability of Bun, you can now use Node.js to create Milkio applications.
20
+
21
+ Whether you are developing locally or running tests, it is all done using Node.js. However, during development, you still need Bun because Milkio relies on Bun to perform automatic generation and many auxiliary operations.
22
+
23
+ You can experience this by running `bun create milkio` and choosing the `node (beta)` template.
24
+
25
+ ## VS Code Template
26
+
27
+ The compatibility issue on Windows has been fixed, and now it works properly on Windows as well.
28
+
29
+ ## Client
30
+
31
+ The issue where the client type did not automatically update on Windows has been resolved, and now it works properly on Windows as well.
32
+
33
+ ## Performance Improvements
34
+
35
+ Now, the startup speed of Milkio on Windows has become very fast.
36
+
37
+ ## Upgrade
38
+
39
+ ```
40
+ bun i milkio@0.6.0
41
+ ```
package/api-test/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import chalk from "chalk";
2
2
  import schema from "../../../generated/api-schema";
3
- import { ExecuteResultFail, type MilkioApp } from "..";
3
+ import { ExecuteResultFail, reject, type MilkioApp } from "..";
4
4
  import { handleCatchError } from "../utils/handle-catch-error.ts";
5
5
 
6
6
  export const executeApiTests = async <Path extends Array<keyof (typeof schema)["apiTestsSchema"]>>(app: MilkioApp, path: Path | string | true | 1 | undefined) => {
@@ -16,8 +16,8 @@ export const executeApiTests = async <Path extends Array<keyof (typeof schema)["
16
16
  const startedAt = new Date().getTime();
17
17
  const apiTestHooks = await import("../../../src/api-test.ts");
18
18
  await apiTestHooks.default.onBootstrap();
19
- const clientPackage = apiTestHooks.default?.client ? (await apiTestHooks.default?.client()) : undefined;
20
- const results: Array<{ path: string, case: number, fail: boolean, failMessage?: string }> = [];
19
+ const clientPackage = apiTestHooks.default?.client ? await apiTestHooks.default?.client() : undefined;
20
+ const results: Array<{ path: string; case: number; fail: boolean; failMessage?: string }> = [];
21
21
 
22
22
  if (!clientPackage) {
23
23
  console.log(`🚨 For testing purposes, if the client package does not exist, subsequent operations might result in errors.`);
@@ -51,12 +51,14 @@ export const executeApiTests = async <Path extends Array<keyof (typeof schema)["
51
51
  }
52
52
  }
53
53
 
54
- const client = clientPackage ? {
55
- execute: async (options?: any) => clientPackage!.execute((path as any), options),
56
- executeOther: async (path: any, options?: any) => clientPackage!.execute((path as any), options),
57
- executeStream: async (options?: any) => clientPackage!.executeStream((path as any), options),
58
- executeStreamOther: async (path: any, options?: any) => clientPackage!.executeStream((path as any), options),
59
- } : undefined;
54
+ const client = clientPackage
55
+ ? {
56
+ execute: async (options?: any) => clientPackage!.execute(path as any, options),
57
+ executeOther: async (path: any, options?: any) => clientPackage!.execute(path as any, options),
58
+ executeStream: async (options?: any) => clientPackage!.executeStream(path as any, options),
59
+ executeStreamOther: async (path: any, options?: any) => clientPackage!.executeStream(path as any, options),
60
+ }
61
+ : undefined;
60
62
 
61
63
  console.log(chalk.hex("#0B346E")(`₋₋₋₋₋₋₋₋`));
62
64
 
@@ -77,20 +79,21 @@ export const executeApiTests = async <Path extends Array<keyof (typeof schema)["
77
79
  await cs.handler({
78
80
  ...((await apiTestHooks.default.onBefore()) ?? {}),
79
81
  log: (...args: Array<unknown>) => console.log(...args),
80
- execute: async (options?: any) => app.execute((path as any), options),
81
- executeOther: async (path: any, options?: any) => app.execute((path as any), options),
82
- executeStream: async (options?: any) => app.executeStream((path as any), options),
83
- executeStreamOther: async (path: any, options?: any) => app.executeStream((path as any), options),
82
+ execute: async (options?: any) => app.execute(path as any, options),
83
+ executeOther: async (path: any, options?: any) => app.execute(path as any, options),
84
+ executeStream: async (options?: any) => app.executeStream(path as any, options),
85
+ executeStreamOther: async (path: any, options?: any) => app.executeStream(path as any, options),
84
86
  client,
85
87
  randParams: () => app.randParams(path as any),
86
88
  randOtherParams: (path: any) => app.randParams(path),
87
89
  reject: (message?: string) => {
88
90
  fail = true;
89
91
  failMessage = message;
92
+ return reject("BUSINESS_FAIL", message ?? "test failed");
90
93
  },
91
94
  });
92
95
  } catch (e: any) {
93
- const response = handleCatchError(e, 'no-execute-id') as ExecuteResultFail;
96
+ const response = handleCatchError(e, "no-execute-id") as ExecuteResultFail;
94
97
  fail = true;
95
98
  failMessage = response.fail.message;
96
99
  }
@@ -102,16 +105,16 @@ export const executeApiTests = async <Path extends Array<keyof (typeof schema)["
102
105
  }
103
106
  results.push({ path, case: i, fail, failMessage });
104
107
  console.log(chalk.hex("#0B346E")(`₋₋₋₋₋₋₋₋`));
105
- await new Promise(resolve => setTimeout(resolve, 64));
108
+ await new Promise((resolve) => setTimeout(resolve, 64));
106
109
  }
107
110
  }
108
111
 
109
112
  const endedAt = new Date().getTime();
110
113
 
111
- const failTotal = results.filter(r => r.fail).length;
114
+ const failTotal = results.filter((r) => r.fail).length;
112
115
  const passTotal = results.length - failTotal;
113
116
 
114
117
  console.log("");
115
118
  if (failTotal === 0) console.log(chalk.hex("#1B813E")(`🥳 all tests ${chalk.hex("#1B813E")(`passed`)} ${chalk.hex("#999A9E")(`🌟 milkio testing took ${((endedAt - startedAt) / 1000).toFixed(2)}s\n`)}`));
116
- else console.log(chalk.hex("#999A9E")(`🤗️️ ${failTotal} test${failTotal > 1 ? "s" : ""} ${chalk.hex("#D75455")(`failed`)}${passTotal > 0 ? `, and ${results.length - failTotal} ${chalk.hex("#1B813E")(`passed`)}` : ''} ${chalk.hex("#999A9E")(`🌟 milkio testing took ${((endedAt - startedAt) / 1000).toFixed(2)}s`)}`));
119
+ else console.log(chalk.hex("#999A9E")(`🤗️️ ${failTotal} test${failTotal > 1 ? "s" : ""} ${chalk.hex("#D75455")(`failed`)}${passTotal > 0 ? `, and ${results.length - failTotal} ${chalk.hex("#1B813E")(`passed`)}` : ""} ${chalk.hex("#999A9E")(`🌟 milkio testing took ${((endedAt - startedAt) / 1000).toFixed(2)}s`)}`));
117
120
  };
@@ -13,43 +13,55 @@ export type ApiTestCases<ApiT extends Api> = {
13
13
  handler: (
14
14
  test: {
15
15
  log: (...params: Array<unknown>) => void;
16
- execute: (options: { params: Parameters<ApiT["action"]>[0], headers?: Record<string, string> } & ExecuteOptions) => Promise<ExecuteResult<Awaited<ReturnType<ApiT["action"]>>>>;
16
+ execute: (options: { params: Parameters<ApiT["action"]>[0]; headers?: Record<string, string> } & ExecuteOptions) => Promise<ExecuteResult<Awaited<ReturnType<ApiT["action"]>>>>;
17
17
  executeOther: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
18
18
  path: Path,
19
19
  options: {
20
- params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
21
- headers?: Record<string, string>
20
+ params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string;
21
+ headers?: Record<string, string>;
22
22
  } & ExecuteOptions,
23
23
  ) => Promise<ExecuteResult<Result>>;
24
- executeStream: (options: { params: Parameters<ApiT["action"]>[0], headers?: Record<string, string> } & ExecuteOptions) => Promise<{
25
- getResult: () => ExecuteResult<undefined>,
26
- stream: AsyncGenerator<Awaited<ReturnType<ApiT["action"]>>>
24
+ executeStream: (options: { params: Parameters<ApiT["action"]>[0]; headers?: Record<string, string> } & ExecuteOptions) => Promise<{
25
+ getResult: () => ExecuteResult<undefined>;
26
+ stream: AsyncGenerator<Awaited<ReturnType<ApiT["action"]>>>;
27
27
  }>;
28
- executeStreamOther: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(path: Path, options: { params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string, headers?: Record<string, string> } & ExecuteOptions) => Promise<{
29
- getResult: () => ExecuteResult<undefined>,
30
- stream: AsyncGenerator<Result>
28
+ executeStreamOther: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
29
+ path: Path,
30
+ options: { params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string; headers?: Record<string, string> } & ExecuteOptions,
31
+ ) => Promise<{
32
+ getResult: () => ExecuteResult<undefined>;
33
+ stream: AsyncGenerator<Result>;
31
34
  }>;
32
35
  client: {
33
- execute: (options: { params: Parameters<ApiT["action"]>[0], headers?: Record<string, string> } & ExecuteOptions) => Promise<ExecuteResult<Awaited<ReturnType<ApiT["action"]>>>>;
36
+ execute: (options: { params: Parameters<ApiT["action"]>[0]; headers?: Record<string, string> } & ExecuteOptions) => Promise<ExecuteResult<Awaited<ReturnType<ApiT["action"]>>>>;
34
37
  executeOther: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
35
38
  path: Path,
36
39
  options: {
37
- params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
38
- headers?: Record<string, string>
40
+ params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string;
41
+ headers?: Record<string, string>;
39
42
  } & ExecuteOptions,
40
43
  ) => Promise<ExecuteResult<Result>>;
41
- executeStream: (options: { params: Parameters<ApiT["action"]>[0], headers?: Record<string, string> } & ExecuteOptions) => Promise<{
42
- getResult: () => ExecuteResult<undefined>,
43
- stream: AsyncGenerator<Awaited<ReturnType<ApiT["action"]>>>
44
+ executeStream: (options: { params: Parameters<ApiT["action"]>[0]; headers?: Record<string, string> } & ExecuteOptions) => Promise<{
45
+ getResult: () => ExecuteResult<undefined>;
46
+ stream: AsyncGenerator<Awaited<ReturnType<ApiT["action"]>>>;
44
47
  }>;
45
- executeStreamOther: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(path: Path, options: { params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string, headers?: Record<string, string> } & ExecuteOptions) => Promise<{
46
- getResult: () => ExecuteResult<undefined>,
47
- stream: AsyncGenerator<Result>
48
+ executeStreamOther: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
49
+ path: Path,
50
+ options: { params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string; headers?: Record<string, string> } & ExecuteOptions,
51
+ ) => Promise<{
52
+ getResult: () => ExecuteResult<undefined>;
53
+ stream: AsyncGenerator<Result>;
48
54
  }>;
49
- }
55
+ };
50
56
  randParams: () => Promise<Parameters<ApiT["action"]>[0]>;
51
57
  randOtherParams: <Path extends keyof (typeof schema)["apiMethodsTypeSchema"]>(path: Path) => Promise<Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0]>;
52
- reject: (message?: string) => void;
58
+ reject: (message?: string) => {
59
+ name: string;
60
+ code: "BUSINESS_FAIL";
61
+ message: string;
62
+ data: string;
63
+ stack: string;
64
+ };
53
65
  } & Awaited<ReturnType<(typeof apiTestHooks)["onBefore"]>>,
54
66
  ) => Promise<void> | void;
55
67
  name: string;
@@ -29,12 +29,11 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
29
29
  runtime.execute.executeIds.add(executeId);
30
30
  const logger = useLogger(executeId);
31
31
  const ip = options.getRealIp ? options.getRealIp(request.request) : (request.request.headers.get("X-Forwarded-For") as string | undefined)?.split(",")[0] ?? "0.0.0.0";
32
- const headers = request.request.headers;
32
+ const headers = request.request.headers as Headers;
33
33
 
34
34
  loggerPushTags(executeId, {
35
35
  from: "http-server",
36
36
  url: fullurl.pathname,
37
- fullurl: fullurl.pathname,
38
37
  ip,
39
38
  method: request.request.method,
40
39
  // @ts-ignore
@@ -77,11 +76,11 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
77
76
  let pathstr = path.join("/") as keyof (typeof schema)["apiMethodsSchema"];
78
77
 
79
78
  const detail = {
80
- ...options.mixin ?? {},
79
+ ...(options.mixin ?? {}),
81
80
  path: pathstr,
82
81
  ip,
83
82
  executeId,
84
- fullurl,
83
+ fullurl: fullurl as URL,
85
84
  request: request.request,
86
85
  response,
87
86
  };
@@ -99,7 +98,7 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
99
98
  if (!detail.response.body) {
100
99
  if (!detail.response.headers["Content-Type"]) detail.response.headers["Content-Type"] = "application/json";
101
100
  if (!detail.response.headers["Cache-Control"]) detail.response.headers["Cache-Control"] = "no-cache";
102
- detail.response.body = `{"executeId":"${executeId}","success":false,"fail":{"code":"NOT_FOUND","message":"${failCode.NOT_FOUND()}"}}`;
101
+ detail.response.body = `{"executeId":"${executeId}","success":false,"fail":{"code":"NOT_FOUND","message":"${failCode.NOT_FOUND(undefined)}"}}`;
103
102
  }
104
103
  await MiddlewareEvent.handle("httpNotFound", [detail]);
105
104
 
@@ -125,7 +124,7 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
125
124
  // execute api
126
125
  // after request middleware
127
126
  await MiddlewareEvent.handle("afterHttpRequest", [headers, detail]);
128
- const mode = (headers.get("Accept")) === "text/event-stream" ? "stream" : "execute";
127
+ const mode = headers.get("Accept") === "text/event-stream" ? "stream" : "execute";
129
128
 
130
129
  const rawbody = await request.request.text();
131
130
  loggerPushTags(executeId, {
@@ -159,7 +158,7 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
159
158
  }
160
159
 
161
160
  if (mode === "execute") {
162
- const result: string = await fn.validateResults(TSON.encode(resultsRaw.$result));
161
+ const result: string = JSON.stringify(TSON.encode(resultsRaw.$result));
163
162
  if (!detail.response.body) detail.response.body = result;
164
163
 
165
164
  // before response middleware
@@ -221,7 +220,7 @@ export function defineHttpHandler(app: MilkioApp, options: ExecuteHttpServerOpti
221
220
  cancel() {
222
221
  control.close();
223
222
  },
224
- } as unknown as UnderlyingByteSource);
223
+ });
225
224
  } else {
226
225
  // node.js or others
227
226
  stream = new ReadableStream({
@@ -285,7 +284,7 @@ export type MilkioHttpRequest = {
285
284
  export type MilkioHttpResponse = Mixin<
286
285
  ResponseInit,
287
286
  {
288
- body: string | BodyInit;
287
+ body: string | Blob | FormData | URLSearchParams | ReadableStream<Uint8Array>;
289
288
  status: number;
290
289
  headers: Record<string, string>;
291
290
  }
package/kernel/context.ts CHANGED
@@ -11,7 +11,7 @@ export type MilkioContext = {
11
11
  * During testing or when calling between microservices, some or all of the values may be undefined
12
12
  */
13
13
  detail: FrameworkHttpDetail;
14
- step: Steps<{}>['step'];
14
+ step: Steps<{}>["step"];
15
15
  };
16
16
 
17
17
  export type FrameworkHttpDetail = {
@@ -24,12 +24,12 @@ export type FrameworkHttpDetail = {
24
24
  };
25
25
 
26
26
  export type Steps<StageT extends Record<any, any>> = {
27
- step: StepFunction<StageT>,
27
+ step: StepFunction<StageT>;
28
28
  // run: <HandlerT extends (stage: StageT) => Record<any, any> | Promise<Record<any, any>>>(handler: HandlerT) => Promise<Awaited<ReturnType<HandlerT>>>,
29
- run: () => Promise<Remove$<StageT>>
30
- }
29
+ run: () => Promise<Remove$<StageT>>;
30
+ };
31
31
 
32
- type StepFunction<StageT extends Record<any, any>> = <HandlerT extends ((stage: Readonly<StageT>) => Record<any, any> | Promise<Record<any, any>>) >(handler: HandlerT) => Steps<Mixin<StageT, ToEmptyObject<Awaited<ReturnType<HandlerT>>>>>
32
+ type StepFunction<StageT extends Record<any, any>> = <HandlerT extends (stage: Readonly<StageT>) => Record<any, any> | Promise<Record<any, any>>>(handler: HandlerT) => Steps<Awaited<StageT> & ToEmptyObject<Awaited<ReturnType<HandlerT>>>>;
33
33
 
34
34
  export const createStep = () => {
35
35
  const stepController = {
@@ -41,15 +41,15 @@ export const createStep = () => {
41
41
  async run() {
42
42
  let stage = {};
43
43
  for (const step of stepController._steps) {
44
- stage = { ...stage, ...(await step(stage)) }
44
+ stage = { ...stage, ...(await step(stage)) };
45
45
  }
46
46
  let result: Record<any, any> = {};
47
47
  for (const key in stage) {
48
48
  const value = (stage as any)[key];
49
- if (!key.startsWith('$')) result[key] = value;
49
+ if (!key.startsWith("$")) result[key] = value;
50
50
  }
51
51
  return result;
52
- }
53
- }
54
- return stepController.step as any as Steps<{}>['step'];
55
- };
52
+ },
53
+ };
54
+ return stepController.step as any as Steps<{}>["step"];
55
+ };
package/kernel/execute.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Context } from "../../../src/context";
2
2
  import { failCode } from "../../../src/fail-code";
3
3
  import schema from "../../../generated/api-schema";
4
- import { type ExecuteId, type ExecuteOptions, type ExecuteResult, createUlid, useLogger, runtime, loggerPushTags, headerToPlainObject, loggerSubmit, type ExecuteCoreOptions, TSON, MiddlewareEvent, reject, _validate, ExecuteStreamResult, createStep } from "..";
4
+ import { type ExecuteId, type ExecuteOptions, type ExecuteResult, createUlid, useLogger, runtime, loggerPushTags, headerToPlainObject, loggerSubmit, type ExecuteCoreOptions, TSON, MiddlewareEvent, reject, _validate, ExecuteStreamResult, createStep, Steps } from "..";
5
5
  import { handleCatchError } from "../utils/handle-catch-error";
6
6
 
7
7
  const apis = new Map<string, any>();
@@ -28,7 +28,7 @@ export async function _call(
28
28
  success: false,
29
29
  fail: {
30
30
  code: "NOT_FOUND",
31
- message: failCode.NOT_FOUND(),
31
+ message: failCode.NOT_FOUND(undefined),
32
32
  data: undefined,
33
33
  },
34
34
  } as ExecuteResult<unknown>;
@@ -55,8 +55,8 @@ export async function _call(
55
55
  path: path as string,
56
56
  headers,
57
57
  logger: options.logger,
58
- detail: options?.detail ?? {} as any,
59
- step: createStep(),
58
+ detail: options?.detail ?? ({} as any),
59
+ step: createStep() as any,
60
60
  };
61
61
 
62
62
  let result: { value: unknown };
@@ -104,8 +104,8 @@ export async function _call(
104
104
  export async function _execute<Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
105
105
  path: Path,
106
106
  options: {
107
- params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
108
- headers?: Record<string, string> | Headers,
107
+ params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string;
108
+ headers?: Record<string, string> | Headers;
109
109
  } & ExecuteOptions,
110
110
  ): Promise<ExecuteResult<Result>> {
111
111
  if (!options.headers) options.headers = {};
@@ -126,7 +126,7 @@ export async function _execute<Path extends keyof (typeof schema)["apiMethodsTyp
126
126
  logger,
127
127
  onAfterHeaders: (headers) => {
128
128
  loggerPushTags(executeId, {
129
- headers: headerToPlainObject(headers),
129
+ requestHeaders: headerToPlainObject(headers),
130
130
  });
131
131
  },
132
132
  });
@@ -141,8 +141,8 @@ export async function _execute<Path extends keyof (typeof schema)["apiMethodsTyp
141
141
  export async function _executeToJson<Path extends keyof (typeof schema)["apiMethodsTypeSchema"]>(
142
142
  path: Path,
143
143
  options: {
144
- params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
145
- headers?: Record<string, string> | Headers,
144
+ params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string;
145
+ headers?: Record<string, string> | Headers;
146
146
  } & ExecuteOptions,
147
147
  ): Promise<string> {
148
148
  const resultsRaw = await _execute(path, options);
@@ -152,17 +152,15 @@ export async function _executeToJson<Path extends keyof (typeof schema)["apiMeth
152
152
  } catch (error) {
153
153
  throw reject("BUSINESS_FAIL", "This is the new API, which takes effect after restarting the server or saving any changes. It will be fixed in the future.");
154
154
  }
155
- const results = await fn.validateResults(TSON.encode(resultsRaw));
155
+ const results = JSON.stringify(TSON.encode(resultsRaw));
156
156
  return results;
157
157
  }
158
158
 
159
-
160
-
161
159
  export async function _executeStream<Path extends keyof (typeof schema)["apiMethodsTypeSchema"], Result extends Awaited<ReturnType<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>>>(
162
160
  path: Path,
163
161
  options: {
164
- params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string,
165
- headers?: Record<string, string> | Headers,
162
+ params: Parameters<(typeof schema)["apiMethodsTypeSchema"][Path]["api"]["action"]>[0] | string;
163
+ headers?: Record<string, string> | Headers;
166
164
  } & ExecuteOptions,
167
165
  ): Promise<ExecuteStreamResult<Path, Result>> {
168
166
  if (!options.headers) options.headers = {};
@@ -183,7 +181,7 @@ export async function _executeStream<Path extends keyof (typeof schema)["apiMeth
183
181
  logger,
184
182
  onAfterHeaders: (headers) => {
185
183
  loggerPushTags(executeId, {
186
- headers: headerToPlainObject(headers),
184
+ requestHeaders: headerToPlainObject(headers),
187
185
  });
188
186
  },
189
187
  });
@@ -193,4 +191,4 @@ export async function _executeStream<Path extends keyof (typeof schema)["apiMeth
193
191
  runtime.execute.executeIds.delete(executeId);
194
192
 
195
193
  return { getResult: () => result.$result, stream: (result as any).$generator } as ExecuteStreamResult<Path, Result>;
196
- }
194
+ }
package/kernel/logger.ts CHANGED
@@ -21,6 +21,7 @@ export type MilkioLoggerTags = {
21
21
  fail?: ExecuteResultFail;
22
22
  timein?: number;
23
23
  timeout?: number;
24
+ result?: unknown;
24
25
  requestHeaders?: Record<string, string>;
25
26
  responseHeaders?: Record<string, string>;
26
27
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "milkio",
3
3
  "type": "module",
4
4
  "module": "index.ts",
5
- "version": "0.7.0-alpha.9",
5
+ "version": "0.8.0",
6
6
  "peerDependencies": {
7
7
  "typescript": "^5.4.2"
8
8
  },
@@ -25,4 +25,4 @@
25
25
  "ts-patch": "^3.1.2",
26
26
  "typescript": "^5.3.3"
27
27
  }
28
- }
28
+ }
@@ -106,7 +106,6 @@ import type * as <%= utils.camel(path.slice(0, -3).replaceAll('/', '$')) %> from
106
106
  type ParamsT = Parameters<typeof <%= utils.camel(path.replaceAll('/', '$').slice(0, -${3})) %>['api']['action']>[0];
107
107
  export const validateParams = async (params: any) => typia.misc.validatePrune<ParamsT>(params);
108
108
  type ResultsT = Awaited<ReturnType<typeof <%= utils.camel(path.replaceAll('/', '$').slice(0, -${3})) %>['api']['action']>>;
109
- export const validateResults = async (results: any) => { _validate(typia.validate<TSONEncode<ExecuteResultSuccess<ResultsT> | ExecuteResultFail>>(results)); return typia.json.stringify<TSONEncode<ExecuteResultSuccess<ResultsT> | ExecuteResultFail>>(results); };
110
109
  export const randParams = async () => typia.random<ParamsT>();
111
110
  `.trim();
112
111
  // export const paramsSchema = typia.json.application<[{ data: ParamsT }], "swagger">();
package/tsconfig.json CHANGED
@@ -27,7 +27,4 @@
27
27
  ]
28
28
  }
29
29
  },
30
- "include": [
31
- "../../../**/*"
32
- ]
33
30
  }
@@ -1,8 +1,8 @@
1
- export const headerToPlainObject = (headers: Headers) => {
1
+ export const headerToPlainObject = (headers: Headers): Record<string, string> => {
2
2
  if (headers.toJSON) return headers.toJSON();
3
3
  const plainHeaders: Record<string, string> = {};
4
4
  headers.forEach((value, key) => {
5
5
  plainHeaders[key] = value;
6
6
  });
7
- return headers;
7
+ return plainHeaders;
8
8
  };