Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blog/fix miyaji blog #165

Merged
merged 3 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"postDate": "2024-06-30T12:49:43.572Z"
"postDate": "2024-06-30T12:49:43.572Z",
"updateDate": "2024-12-17T02:07:58.751Z"
}
3 changes: 2 additions & 1 deletion src/content/blog-metas/2024-07-05-gas-environment.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"postDate": "2024-07-05T13:21:25.015Z"
"postDate": "2024-07-05T13:21:25.015Z",
"updateDate": "2024-12-17T02:07:58.752Z"
}
3 changes: 2 additions & 1 deletion src/content/blog-metas/2024-12-15-hono-typia-openapi.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"postDate": "2024-12-15T14:30:40.899Z"
"postDate": "2024-12-15T14:30:40.899Z",
"updateDate": "2024-12-17T02:07:58.753Z"
}
44 changes: 39 additions & 5 deletions src/content/blogs/2024-06-30-esbuild-plugin-gas-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ author: miyaji
tags: [node, esbuild, javascript, gas]
---

exportした関数のエントリーポイントを自動で生成するesbuildプラグイン **esbuild-plugin-gas-generator** を作成しました。
GAS開発ではnpmライブラリを使うためにバンドルを行う必要があります。加えて、GASでエントリーポイントとして認識されるためには`function`を使って定義されている必要があります。

そこで、exportした関数のエントリーポイントを自動で生成するesbuildプラグイン **esbuild-plugin-gas-generator** を作成しました。

ESModuleとタイトルに書きましたがESModuleをバンドルできるというだけで、`import.meta`や Top Level Await は使えません。ご了承ください。

https://github.com/miyaji255/esbuild-plugin-gas-generator

https://www.npmjs.com/package/esbuild-plugin-gas-generator

## 使い方

build.jsに以下のように記述することで使用できます。プラグインの都合上bundleとformatは`true`と`'esm'`であることが必須です。
build.jsに以下のように記述することで使用できます。プラグインの都合上bundleとformatは`true`と`'iife'`であることが必須です。

出力ファイルはoutfileかオプションのtargetsで指定する。

Expand All @@ -25,14 +29,21 @@ const GasPlugin = require('esbuild-plugin-gas-generator');
esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
format: 'esm',
format: 'iife',
outfile: 'dist/bundle.js',
plugins: [GasPlugin()],

// targetsで指定する場合
plugins: [
GasPlugin({
targets: ['dist/bundle.js']
// appsscript.json のパスを指定する
appsscript: "appsscript.json",
// appsscript.json の内容を直接指定する
appsscript: {
timeZone: "Asia/Tokyo",
dependencies: {},
exceptionLogging: "STACKDRIVER",
runtimeVersion: "V8"
}
})
]
}).catch((e) => {
Expand All @@ -51,6 +62,27 @@ export function hello() {

## 実装

`export`されたシンボルを収集するためにv2ではesbuildのmetafileという機能を使いました。これはbuild結果からimport/exportの情報を取得できる機能です。

つまり、build中にもう一度buildしているということです。他のプラグインも2度ビルドしている場合、競合する可能性があるので`excludePlugins`で除外することができます。

こうして作成したメタデータから次のようなコードを生成します。

```javascript
function hello() {}
"use strict";
var _exports = (()=>{
function hello() {
console.log("hello")
}
return {hello}
})();
Object.assign(globalThis, _exports);
```

<details>
<summary>v1の実装</summary>

meriyahでパースしてexportした変数をすべて以下のように変換します

```javascript
Expand All @@ -63,3 +95,5 @@ function hello() {
globalThis.hello=hello;
})()
```

</details>
33 changes: 8 additions & 25 deletions src/content/blogs/2024-07-05-gas-environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,17 @@ import GasGeneratorPlugin from 'esbuild-plugin-gas-generator'
build({
entryPoints: ['src/index.ts'],
bundle: true,
format: "esm",
format: "iife",
outfile: 'dist/index.js',
plugins: [GasGeneratorPlugin()],
plugins: [GasGeneratorPlugin({
appsscript: "appsscript.json"
})],
}).catch((e) => {
console.error(e)
process.exit(1)
})
```

さらに、`appsscript.json`を自動でコピーするように次のようなプラグインを足します。

```ts
const copyAppsScriptPlugin = {
name: "copy-appsscript",
setup(build) {
build.onEnd(async () => {
await copyFile('appsscript.json', 'dist/appsscript.json')
})
}
}
```

esbuildには標準でwatchモードがあります。これを使うとファイルを変更すると自動的にビルドされます。引数で分岐してbuildとwatchを切り替えることができるようにした、最終的なビルドスクリプトは次のようになります。

```ts
Expand All @@ -78,17 +67,11 @@ async function main() {
entryPoints: ["src/index.ts"],
bundle: true,
outfile: "dist/index.js",
format: "esm",
format: "iife",
plugins: [
GasGeneratorPlugin(),
{
name: "copy-appsscript",
setup(build) {
build.onEnd(async () => {
await copyFile("appsscript.json", "dist/appsscript.json")
})
}
}
GasGeneratorPlugin({
appsscript: "appsscript.json"
}),
],
} as const satisfies BuildOptions

Expand Down
12 changes: 6 additions & 6 deletions src/content/blogs/2024-12-15-hono-typia-openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Hono + Typia で OpenAPI ドキュメントを生成する
description: Hono + Typia で作成した Hono の型から OpenAPI ドキュメントを生成するライブラリを作りました。
category: tech
author: miyaji
tags: [advent-calendar, javascript, typescript, openapi, hono, typia]
tags: [advent-calendar, javascript, typescript, openapi, hono, typia, rest-api]
---

この記事は、[OUCC Advent Calendar 2024](https://adventar.org/calendars/10655) の 15 日目の記事です。昨日は watamario さんの [AtCoder Beginners Selection の Shift only を x86 の bsf 命令で解く](/blog/articles/2024-12-14-bsf/) でした。本日は、私が作成したHono + Typia で作成した Hono の型から OpenAPI ドキュメントを生成するライブラリについて説明します。
Expand All @@ -14,13 +14,13 @@ https://github.com/miyaji255/hono-typia-openapi

## 動機

Hono には [@honojs/zod-openapi](https://hono.dev/examples/zod-openapi) というライブラリがあり、これを利用することでOpenAPIドキュメントを生成することができます。
Hono には [@hono/zod-openapi](https://hono.dev/examples/zod-openapi) というライブラリがあり、これを利用することでOpenAPIドキュメントを生成することができます。

しかし、このライブラリはその名の通りZodにしか対応しておらず、書き方もHonoから大きく変えることになり使いづらいです。TypiaはZodよりも高速なので[^1]、できることならばTypiaを使いたいところです。そこで、Honoの持つSchemaの型からOpenAPIドキュメントを生成するライブラリを作成しました。

また、型から生成することにより完全なゼロランタイムでOpenAPIドキュメントを生成することができます。

ちなみに、同じように @honojs/zod-openapi が使いづらいということで [Hono OpenAPI](https://github.com/rhinobase/hono-openapi) というライブラリも作成されています。これは Zod の他にも Valibot, Ark, TypeBox に対応していますが、Typia には対応していません。
ちなみに、同じように @hono/zod-openapi が使いづらいということで [Hono OpenAPI](https://github.com/rhinobase/hono-openapi) というライブラリも作成されています。これは Zod の他にも Valibot, Ark, TypeBox に対応していますが、Typia には対応していません。

## 使い方

Expand Down Expand Up @@ -170,15 +170,15 @@ export default defineConfig({

### Hono app の作成方法

Hono app は`@honojs/typia-validator`を使用することで自動的に型が指定されます。
Hono app は`@hono/typia-validator`を使用することで自動的に型が指定されます。

注意事項としてはメソッドチェーンの形式で書かないと型が正しく扱われないことです。これは Hono Client も同様なのですが、メソッドチェーンにしないと変数の型がスキーマを表す型にならないためです。

逆にこれを利用することでスキーマに出力しないエンドポイントを作ることもできます。

```typescript
import { Hono } from 'hono';
import { typiaValidator } from '@honojs/typia-validator/http';
import { typiaValidator } from '@hono/typia-validator/http';
import typia, { type tags } from 'typia';

interface User {
Expand Down Expand Up @@ -221,7 +221,7 @@ if文で環境変数を見ているのは開発環境でのみ swagger UI を表

```typescript
import { Hono } from 'hono';
import { typiaValidator } from '@honojs/typia-validator/http';
import { typiaValidator } from '@hono/typia-validator/http';
import typia, { type tags } from 'typia';

interface User {
Expand Down