## 経緯
[[JSR]]が[[Deno]]以外にも対応しており、以下の点で魅力を感じているので、utility的なライブラリの登録を試してみたい。
- [[TypeScript]]のソースコードをそのまま登録できる
- ドキュメントなども勝手に生成してくれる
## 最終目的
[[🦉Silhouette]]からコアロジックを切り出して `silhouette-core` としてパッケージ登録したい。ただ、その前に簡単なライブラリを登録・利用できることを試す。
## 環境
```console
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.4 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
```
```console
$ deno --version
deno 2.0.2 (stable, release, x86_64-unknown-linux-gnu)
v8 12.9.202.13-rusty
typescript 5.6.2
```
## プロジェクト作成
```console
deno init minerva-test
```
## 依存packageの追加
依存関係なしだと面白くないので、[[🦉Owlelia]]を依存関係に追加してみる。
```console
$ deno add npm:owlelia
Add npm:
[email protected]
```
## コードを書く
2つほど公開関数を書く。パッケージ公開のページを参考に注意しながら。
<div class="link-card">
<div class="link-card-header">
<img src="https://jsr.io/logo-square.svg?__frsh_c=3ec9968243e86c80ab304587033785dab6e0158d" class="link-card-site-icon"/>
<span class="link-card-site-name">jsr.io</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">Publishing packages - Docs - JSR</p>
<p class="link-card-description">Learn how to publish packages to JSR.</p>
</div>
</div>
<a href="https://jsr.io/docs/publishing-packages"></a>
</div>
> [!thinking]
> 以下の記載が少し気になるが、実装するライブラリが[[CommonJS]]の`require`などを記載していなければ大丈夫という理解ではいる。
>
> **ESM modules only**: JSR packages are published as ESM modules. This means that you can only publish modules that use the import and export keywords. You cannot publish CommonJS modules.
>
> 依存パッケージや、これを利用するパッケージにまで求められるのかはちゃんと分かっていないので要確認。以下のようにあるが、[[TypeScript]]が[[CommonJS]]に[[トランスパイル]]する分には大丈夫と信じたい...。
>
> To publish a JSR package, you must first write the code for your package. JSR packages are written in JavaScript or TypeScript, and are published as ESM modules.
ドキュメントでは `mod.ts` がエントリポイントになってそうなので作成する。
`mod.ts`
```ts
import { DateTime } from "owlelia";
/**
* 現在の日付を文字列で返却
* @returns YYYY-mm-dd (ex: 2024-10-19)
*/
export function getCurrentDate(): string {
return DateTime.now().displayDate;
}
/**
* 1日後の日付にする
*
* @param datetime 対象日付
* @returns 1日後の日付
*/
export function plusOneDay(datetime: DateTime): DateTime {
privateMethod();
return datetime.plusDays(1);
}
function privateMethod(): void {
// do nothing
}
```
既存コードは一旦すべて消す。
```console
rm main.ts maint_test.ts
```
## 設定ファイルの追加
[[Deno]]利用なので`jsr.json`の作成は不要。`deno.json`を編集。`name`, `version` を適当に追加し、`exports`にはエントリポイントである`mod.ts`を指定。
```json
{
"name": "@tadashi-aikawa/minerva-test",
"version": "0.1.0",
"exports": "./mod.ts",
"tasks": {
"dev": "deno run --watch main.ts"
},
"imports": {
"@std/assert": "jsr:@std/assert@1",
"owlelia": "npm:owlelia@^0.48.1"
}
}
```
## スコープとパッケージの作成
[[スコープ (JSR)|スコープ]]と[[パッケージ (JSR)|パッケージ]]の作成は以下から行える。
<div class="link-card">
<div class="link-card-header">
<img src="https://jsr.io/logo-square.svg?__frsh_c=3ec9968243e86c80ab304587033785dab6e0158d" class="link-card-site-icon"/>
<span class="link-card-site-name">jsr.io</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">Publish a package - JSR</p>
<p class="link-card-description">Create a package to publish on JSR.</p>
</div>
</div>
<a href="https://jsr.io/new"></a>
</div>
作成成功すると以下のようなページが表示される。
![[Pasted image 20241019202315.png|frame]]
先にこちらを実施してから[[#設定ファイルの追加]]を行った方が楽だった。。
## 公開
publishする。
```console
$ deno publish
Check file:///home/tadashi-aikawa/tmp/minerva-test/mod.ts
Checking for slow types in the public API...
Check file:///home/tadashi-aikawa/tmp/minerva-test/mod.ts
error[missing-license]: missing license field or file
--> /home/tadashi-aikawa/tmp/minerva-test/deno.json
= hint: add a "license" field. Alternatively, add a LICENSE file to the package and ensure it is not ignored from being published
docs: https://jsr.io/go/missing-license
error: Found 1 problem
```
### ノーライセンスエラー
ライセンス情報がないとエラーになるっぽい。
<div class="link-card">
<div class="link-card-header">
<img src="https://jsr.io/logo-square.svg?__frsh_c=3ec9968243e86c80ab304587033785dab6e0158d" class="link-card-site-icon"/>
<span class="link-card-site-name">jsr.io</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">Troubleshooting - Docs - JSR</p>
<p class="link-card-description">Troubleshooting common issues with JSR.</p>
</div>
</div>
<a href="https://jsr.io/docs/troubleshooting#missinglicense"></a>
</div>
今回は `deno.json` に`license`を追加する。`LICENSE.md`があればそれでOK。
```json
{
"name": "@tadashi-aikawa/minerva-test",
"version": "0.1.0",
"exports": "./mod.ts",
"license": "MIT",
"tasks": {
"dev": "deno run --watch main.ts"
},
"imports": {
"@std/assert": "jsr:@std/assert@1",
"owlelia": "npm:owlelia@^0.48.1"
}
}
```
リトライ。
```console
$ deno publish
```
ブラウザが開いてサインインを求められた。第3者が公開できたらまずいのでそれは当然。
![[Pasted image 20241019202708.png|frame]]
最終的には[[GitHub Actions]]でpublishする予定なので、トークン利用の方法を試そう... と思ったが、どうやら[[GitHub Actions]]はそんな手間も不要みたいである。
> JSR has first class support for publishing packages from GitHub Actions. This allows you to publish packages automatically from CI without you having to configure any secrets or authentication.
> *[Publishing packages \- Docs \- JSR](https://jsr.io/docs/publishing-packages#publishing-from-github-actions)*
というわけでおとなしくブラウザから認証する。
![[Pasted image 20241019203236.png|frame]]
こんな画面になるので `Approve` を押す。
### 結果確認
結果は https://jsr.io/@tadashi-aikawa/minerva-test で確認できる。
![[Pasted image 20241019203518.png|frame]]
*ドキュメント. クリックするとより詳細が表示される*
![[Pasted image 20241019203615.png|frame]]
*ソースコードが確認できる*
他にも過去のリリースバージョンや依存関係、スコアなどが確認できる。
## パッケージを利用する
`@tadashi-aikawa/minerva-test` を利用してみる。[[Deno]]プロジェクトと[[Node.js]]プロジェクト、[[Bun]]プロジェクトの3通りを試してみる。
### Denoプロジェクト
流石にこちらはスムーズ。
```console
deno init sandbox1
cd $_
deno add jsr:@tadashi-aikawa/minerva-test
```
インストール成功したら`main.ts`を編集。
```ts
import { getCurrentDate } from "@tadashi-aikawa/minerva-test";
if (import.meta.main) {
console.log(getCurrentDate());
}
```
正常に動作することを確認。
```console
$ deno run main.ts
2024-10-19
```
> [!positive] コードジャンプで[[TypeScript]]のソースコードがそのまま見られたりするのは良い。
### Node.jsプロジェクト
こちらは少し心配。[[pnpm]]を使った[[Node.js]]プロジェクトで試してみる。
```console
mkdir sandbox2
cd $_
pnpm init
pnpm i -D typescript
```
[[pnpm]]のインストールコマンドは[[JSR]]のパッケージページで確認できる。やはり[[JSR]]のCLIを利用する必要がありそう。
```console
$ pnpm dlx jsr add @tadashi-aikawa/minerva-test
! The local project doesn't define a 'packageManager' field. Corepack will now add one referencing
[email protected]+sha512.38dc6fba8dba35b39340b9700112c2fe1e12f10b17134715a4aa98ccf7bb035e76fd981cf0bb384dfa98f8d6af5481c2bef2f4266a24bfa20c34eb7147ce0b5e.
! For more details about this field, consult the documentation at https://nodejs.org/api/packages.html#packagemanager
Packages: +4
++++
Progress: resolved 4, reused 1, downloaded 3, added 4, done
Setting up .npmrc...ok
Installing @tadashi-aikawa/minerva-test...
$ pnpm add @tadashi-aikawa/minerva-test@npm:@jsr/tadashi-aikawa__minerva-test
Packages: +3
+++
Progress: resolved 3, reused 2, downloaded 1, added 3, done
dependencies:
+ @tadashi-aikawa/minerva-test <- @jsr/tadashi-aikawa__minerva-test 0.1.0
Done in 1.5s
Completed in 1s
```
ちょっと警告が出たものの `package.json` には追加されてそう。
```json
{
"name": "sandbox2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "
[email protected]+sha512.38dc6fba8dba35b39340b9700112c2fe1e12f10b17134715a4aa98ccf7bb035e76fd981cf0bb384dfa98f8d6af5481c2bef2f4266a24bfa20c34eb7147ce0b5e",
"dependencies": {
"@tadashi-aikawa/minerva-test": "npm:@jsr/tadashi-aikawa__minerva-test@^0.1.0"
}
}
```
もちろん `node_modules` にも。
```console
$ tree node_modules
node_modules
└── @tadashi-aikawa
└── minerva-test -> ../.pnpm/@
[email protected]/node_modules/@jsr/tadashi-aikawa__minerva-test
```
`main.ts`を作成する。
```ts
import { getCurrentDate } from "@tadashi-aikawa/minerva-test";
console.log(getCurrentDate());
```
1行目にエラー。
```error
• Cannot find module '@tadashi-aikawa/minerva-test' or its corresponding type declarations.
There are types at '/home/tadashi-aikawa/tmp/sandbox2/node_modules/@tadashi-aikawa/minerva-test/_dist/mod.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'. [2307]
```
`tsconfig.json`を作成し忘れていたので追加。この設定にしたのは[[🦉Various Complements]]の挙動を確認したかったからで深い意味はない。
```json
{
"compilerOptions": {
"strict": true,
"baseUrl": ".",
"module": "ESNext",
"target": "es2018",
"allowJs": true,
"strictPropertyInitialization": false,
"moduleResolution": "node",
"importHelpers": true,
"isolatedModules": true,
"lib": ["dom", "es5", "es6", "es7"],
"allowSyntheticDefaultImports": true
},
"include": ["**/*.ts", "**/*.mts"]
}
```
[[moduleResolution (tsconfig)|moduleResolution]]を`bunder`に変更して一旦解決。実行確認。
```console
$ pnpm exec tsc
```
`package.json`の`type`が`module`でないと警告が出るので変更してから実行した。
```console
$ node main.js
2024-10-19
```
ここまでの挙動からして、[[CommonJS]]が絡んでくるとかなりの確率で動かなくなりそうな予感はしている...。
### Bunプロジェクト
```console
mkdir sandbox3
cd $_
bun init -y
```
インストールも順調。
```console
$ bunx jsr add @tadashi-aikawa/minerva-test
bun add v1.1.30 (7996d06b)
installed @tadashi-aikawa/
[email protected]
3 packages installed [1470.00ms]
Completed in 1s
```
`index.ts`の編集。
```ts
import { getCurrentDate } from "@tadashi-aikawa/minerva-test";
console.log(getCurrentDate());
```
エラーも出ないので実行。拍子抜けなくらいアッサリ動いた。
```console
$ bun .
2024-10-19
```
## Silhouetteのプロジェクトで利用する
最終目的である[[🦉Silhouette]]でこのライブラリが利用可能であるかを試す。[[🦉Silhouette]]は[[Bun]]プロジェクトだが、[[moduleResolution (tsconfig)|moduleResolution]]は`node`であるため懸念はある。
<div class="link-card">
<div class="link-card-header">
<img src="https://github.githubassets.com/favicons/favicon.svg" class="link-card-site-icon"/>
<span class="link-card-site-name">GitHub</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">GitHub - tadashi-aikawa/silhouette: Obsidianでシンプルにタスクを管理するためのプラグイン</p>
<p class="link-card-description">Obsidianでシンプルにタスクを管理するためのプラグイン. Contribute to tadashi-aikawa/silhouette de ... </p>
</div>
<img src="https://opengraph.githubassets.com/b5abfcf3d688a1ef7e5071b562cd0405f731b43f88bf7017bbc088c8c328a724/tadashi-aikawa/silhouette" class="link-card-image" />
</div>
<a href="https://github.com/tadashi-aikawa/silhouette"></a>
</div>
インストール手順は省略。案の定問題が発生...。
```error
• Cannot find module '@tadashi-aikawa/minerva-test' or its corresponding type declarations.
There are types at '/home/tadashi-aikawa/git/github.com/tadashi-aikawa/silhouette/node_modules/@tadashi-aikawa/minerva-test/_dist/mod.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'. [2307]
```
[[moduleResolution (tsconfig)|moduleResolution]]が`node`だったので`bundler`にしたら動いた。[[moduleResolutionはbundlerがオススメ (tsconfig)|moduleResolutionはbundlerがオススメ]]とあったし問題なかろう。
## Silhouette Core
[[🦉Silhouette Core]]を[[GitHub]]に作成。続けてローカルにプロジェクト作成。
```console
deno init silhouette-core
```
実装していく。
## semantic-releaseの設定
[[JSR]]にパッケージ公開するために[[semantic-release-jsr]]を使う。
`.releaserc.mjs`
```js
export default {
branches: ["main"],
plugins: [
[
"@semantic-release/commit-analyzer",
{
preset: "conventionalcommits",
releaseRules: [
{ breaking: true, release: "minor" }, // TODO: v1になったら release: "major" にする
{ type: "feat", release: "minor" },
{ type: "build", release: "minor" },
{ type: "style", release: "minor" },
{ type: "fix", release: "patch" },
{ type: "refactor", release: "patch" },
{ revert: true, release: "patch" },
],
},
],
[
"@semantic-release/release-notes-generator",
{
preset: "conventionalcommits",
presetConfig: {
types: [
{ type: "feat", section: "✨ Features" },
{ type: "style", section: "🎨 Styles" },
{ type: "fix", section: "🛡️ Bug Fixes" },
{ type: "build", section: "🤖 Build" },
{ type: "docs", hidden: true },
{ type: "refactor", hidden: true },
{ type: "test", hidden: true },
{ type: "ci", hidden: true },
{ type: "dev", hidden: true },
{ type: "chore", hidden: true },
],
},
},
],
"@sebbo2002/semantic-release-jsr",
"@semantic-release/github",
[
"@semantic-release/git",
{
assets: ["deno.json"],
message:
"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
},
],
],
};
```
## GitHub Actionsの設定
`permissions`に`id-token: write`が必要なので忘れずに。また、[[JSR]]実行部分は[[Deno]]をインストールする必要はない。[[jsr (npm)|jsr]]を使っているので[[npm]]ベースプロジェクトであれば実行できるため。
```yaml
name: "Release"
on: workflow_dispatch
permissions:
contents: write
id-token: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm i -D --no-save conventional-changelog-conventionalcommits @semantic-release/git @sebbo2002/semantic-release-jsr
- name: "Release"
uses: cycjimmy/semantic-release-action@v4
with:
semantic_version: 24.2.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
## バージョンがいきなり1.0.0に!?
[[JSR]]に登録してしまったのでもう引き返せない。。orz
今までは1未満でもちゃんとバージョニングしてくれていたが、`package.json`の`private: true`があったから許されていたのかもしれない...。`deno.json`は`private`はなさそうだし、[[JSR]]にデプロイしている時点でprivateでもないのでいかんきがする。
[[🦉Owlelia]]はどうして平気なんだ... と思ったけど、まだ[[semantic-release]]でリリースはしていなかった。今後予定はあるので要注意だな...。
[[🦉ghostwriter.nvim]]はちゃんとマイナーバージョンをつけられている。これはなぜなんだろう。。もしかしてgit tagの状態が関係していたとか...? いずれにしてもLocalでちゃんと確認しよう...。[[semantic-release]]のバージョンかもしれないし...。
## 今度はちゃんとLocalで確認
> [[📕semantic-releaseをローカルでデバッグ]]
## Silhouette Coreを使ってみる
sandboxプロジェクトで使ってみる。
```console
toki deno deno-sandbox
cd $_
deno add jsr:@tadashi-aikawa/silhouette-core
```
普通に動いてそうだったのでOK。
```ts
import { Repetition } from "@tadashi-aikawa/silhouette-core";
if (import.meta.main) {
const reps = Repetition.fromRepetitionsStr("non workday|tue/wed");
reps.forEach((r) => console.log(r));
}
```