新年が始まったわけだが
2019年
まぁホントに色々やったんだけど、ギョームとしては、WebRTC沼に参戦したこととPureScript及び俺製VirtualDOMのpurescript-freedomをぶちこんだこととか 、AWSからGCPのインフラ移行やったのとかログ基盤作ったりあたりがトピックかな。 今年はわりと大げさめなタスク多かったかも。 WebRTC一本で飯食える人がいる意味がよくわかった。商用SFUさまさまです。
プライベートは二人の子供に振り回されててんやわんやしてた。一日のうちに何に体力を使うかの配分について改善のしようがある。
家を買おうとして9000万の家でも買えるとファイナンシャルプランナーに言われたが、自分で正確なライフプラン表つくったら絶対に買えないレベルだったのでファイナンシャルプランナーの言うことを鵜呑みにしてはいけない、というかあいつらもただソフトに適当に数字打ち込んで御託並べてるだけなので信用してはいけない。
2020年
今年は自分のサービスで少しでも売上を立てる年にする。 歳をとって待つのが得意になったので長い目で見ながらやっていく。
家は買いたいけど新築はやっぱり無駄に高い。中古を狙っている。 家持ってる人で家売りたい人は、twitterの@oreshinyaまで連絡ください。買いたいエリアだったら検討します。
PureScriptのJWT用のライブラリを作りました
PureScriptのJWT用ライブラリ、purescript-simple-jwtを作りました。
一応既存のものでpurescript-jwt
というライブラリがありましたが、デコード専用、且つ、署名の検証もしないものだったので、自分で作ることにしました。
使い方
エンコード
encode :: forall payload. WriteForeign payload => Secret -> Algorithm -> payload -> Effect Jwt
シークレットとアルゴリズムとペイロードを渡します。 アルゴリズムついては、HS256とHS512に対応しています。 ペイロードについては、仕様上不定なので、まぁ適当にレコード渡してください。
デコード
decode :: forall payload. ReadForeign payload => Secret -> Jwt -> Effect (Either JwtError payload)
シークレットとJWTを渡します。検証時に用いるアルゴリズムはJWTのヘッダから勝手に選びます。
トークンがおかしかったり、検証に失敗したりするとエラーが返ってきます。
ペイロードの中身を使ったチェック(例えば、exp
等による有効期限チェック)については、このライブラリの責務の範囲外としています。
purescript/package-setsにコントリビュートしてみた(とUIライブラリの宣伝)
package-setsとは
package-setsとは、公式が管理している、各パッケージのリポジトリやバージョンが記載されたセットです。 このpackage-setsにおいて各パッケージのバージョンはただひとつだけ含まれており、package-setsに含まれたものはコンパイルが保証されています。package-sets自体にもバージョンのような概念があり(といってもタグなんですが)、package-setsが更新されたりすると新しくタグがきられます。
PureScriptのパッケージ管理はBowerという印象が強い方がまだ多くいますが、psc-packageやspagoというものがあり、これらは指定したpackage-setsとタグをもとにパッケージをインストールできます。
余談ですが、この仕組みは裏を返せばpackage-setsにないものは管理できないということであり、かつてはpackage-setsに自分でパッケージを追加するか、forkして編集したpackage-setsを使うかしかなかったのですが、spagoというパッケージマネージャ兼ビルドツールが出てきて、package-setsをforkしなくてもpackage-setsにないパッケージを管理できるようになりました。
願望も含まれてますが、わたし的にはspago一強になるのではないかと思ってます。
さて、余談はさておき、そんなpackage-setsですが、package-setsに登録されているライブラリが増えるのはとても良いことだと思います。
最近package-setsにパッケージを追加したので、今日はpackage-setsの追加の仕方を紹介します。
前提条件
package-setsは基本的にどんなパッケージでも追加はウェルカムだそうです。 ただし、現時点では、以下の基準を満たしてなければいけません。
pulp version
をバージョニングに使用することpulp publish
をつかってパッケージを公開することbower -i -p
でインストールしたパッケージが正しく動くこと
pulpとは昔からあるビルドツールです。
pulp version
を使ってほしい理由は、タグがv
から始まってほしいからだそうです。pulp version
はv
から始まるタグをつけてくれます。
pulp publish
とは、パッケージをBowerにあげて、ドキュメントをPursuitというドキュメントサイトにアップロードをするコマンドです。配布方法がpackage-setsだけではなくBowerも存在しているためにこのコマンドで配布してね、ということみたいです。
bower -i -p
でインストールしたパッケージが正しく動くことを期待するのも上記の理由でしょう。
とまぁまだBowerの存在感がしっかり残っています。
現状だと、事実上、ライブラリを書く時のみ、pulpとbowerは捨てにくいです。
しかしながら、以下のような動きが始まっており、ゆっくりと時間をかけてBowerの存在感がなくなっていくことを期待しましょう。
準備
package-setsにpackageを追加する前に以下の依存をインストールしておきましょう。
私の場合は、こういうスポットで使うとき用の雑なDockerイメージをもっていて、それをちょっと改変して使いました。 雑ですがインストール作業すらしたくなければ適宜変更して使ってください。
FROM node:10.14.0 ENV HOME /home/node RUN set -ex \ && apt-get update \ && apt-get install -y lsof jq \ && cd /tmp \ # Install dhall && curl -fsSL -O https://github.com/dhall-lang/dhall-haskell/releases/download/1.21.0/dhall-1.21.0-x86_64-linux.tar.bz2 \ && tar xvjf dhall-1.21.0-x86_64-linux.tar.bz2 && mv bin/dhall /usr/local/bin/dhall \ && chmod +x /usr/local/bin/dhall \ # Install dhall-to-json && curl -fsSL -O https://github.com/dhall-lang/dhall-haskell/releases/download/1.21.0/dhall-json-1.2.7-x86_64-linux.tar.bz2 \ && tar xvjf dhall-json-1.2.7-x86_64-linux.tar.bz2 && mv bin/dhall-to-json /usr/local/bin/dhall-to-json \ && chmod +x /usr/local/bin/dhall-to-json \ # Install psc-package && curl -fsSL -O https://github.com/purescript/psc-package/releases/download/v0.5.1/linux64.tar.gz \ && tar xvzf linux64.tar.gz && mv psc-package/psc-package /usr/local/bin/psc-package \ && chmod +x /usr/local/bin/psc-package \ # Install purs && curl -fsSL -O https://github.com/purescript/purescript/releases/download/v0.12.3/linux64.tar.gz \ && tar xvzf linux64.tar.gz && mv purescript/purs /usr/local/bin/purs \ && chmod +x /usr/local/bin/purs USER node WORKDIR $HOME/app
作業
とりあえず、package-setsをforkしてcloneしましょう。
package-setsは、dhallという言語で管理されているのでdhallを書くわけですが、知らなくても大丈夫です。
他のファイルを見れば書き方はわかります。src
以下にもぐって、マネッコして書きましょう。
さて、書き終わったら、make setup
を叩きます。
これで、packages.json
ってのが更新されてdiffにでてくるはずなので、中身を見て、自分が足したpackageが間違いなく足されているのかを確認しましょう。
そのあとは、自分の追加したpackageをverifyします。
たとえば、あなたがpackage-setsにeternal-force-blizzard
というパッケージを追加したのであれば、psc-package verify eternal-force-blizzard
と打ちましょう。
依存をインストールしてコンパイルを行います。無事に終了すればOKです。
まぁよくわかんなかったら、コントリビューションガイドに親切に書いてあるので見てみましょう。
PR
ここまでできたらあとはPRを送るだけです。今回は私もはじめてだったので一応「俺のライブラリ入れていい?」って感じでPRを送りました。 また、他人のパッケージもひとつ追加する必要があったのでそれも追加しました。たぶん他人のライブラリも前提条件を満たしていてverifyが通れば追加して問題なさそうです。実際に私のパッケージも既に一つ存在していました。
以下は私が送ったPRです。dhallの編集の仕方がわかんなかったら参考にしてください。
一度に大量に追加したのでかなり疲れました...。
夜中にPR送ったのですが、起きたらマージされていて、新しいpackage-setsがリリースされてました!ありがたい!!
とまぁ、ちょっとめんどくさいんですけど、簡単です!
宣伝
最近、ちゃんと業務で使えるものを目指して、PureScript向けのUIライブラリをつくりました。
purescript-freedomと言います。
npm dependencyはありません。
このパッケージは既存のパッケージで使いたいと思うものがなかったことが原因でつくったため、 既存のUIパッケージとの差別化がされています。
ガイドやサンプルプロジェクトも用意していて、すでに派生パッケージもいくつか公開しています。
ElmからPureScriptに興味を持った人、HalogenやPux、react-basicになにかしら気に入らないことがある人、「あぁ?なんだどういうもんかみてやろうじゃねえか?」という人、騙されたと思って見てくれると嬉しいです。
ホントに騙しちゃったらごめんなさい、許してね♡
2020/07/07 追記
新たにUIライブラリ、purescript-grainをリリースしました。 チューニングもしてあるのでそちらのほうがおすすめです。
purescript-bucketchainの紹介
はじめに
rackやexpress, koaのようなウェブサーバーのための共通のインターフェースを提供するライブラリをつくりました。 それがpurescript-bucketchainです。
背景
外部のnpm packageに頼らず、ランタイムがnodejsなのでパイプで上手くやってくれるようにストリームベースなインターフェースで、koaとかexpressっぽさを踏襲しつつ、ミドルウェアを積みまくってサーバーを構築できるような基盤がほしくなりました。
使い方の流れ
ミドルウェアを用意する
特定のpathで特定の画像を返すミドルウェアをつくってみましょう。 まずは以下を見てください。
middleware :: Middleware middleware next = do http <- ask if requestMethod http == "GET" && requestURL http == "/img" then liftEffect do setStatusCode http 200 setHeader http "Content-Type" "image/png" Just <<< fromReadable <$> createReadStream "example/300x300.png" else next
Middleware
はHandler (Maybe ResponseBody) -> Handler (Maybe ResponseBody)
の型シノニムです。
つまりnext
はHandler (Maybe ResponseBody)
です。
middleware1 <<< middleware2
のような形でミドルウェアを結合して組み合わせて一つのミドルウェアをつくります。
ResponseBody
はその名の通りレスポンスのボディですが、実態はReadable Streamとなっており、Readable StreamであればResponseBodyに変換可能です。また、String
からResponseBody
をつくることも可能です。
Maybe ResponseBody
となっていますが、Nothing
の場合だとボディ無しでレスポンスを返します。
当然next
を呼び出さなければ次のミドルウェアの処理には移りません。
Handler
モナドは、非同期な処理が中心のnodejsで、ミドルウェアがシーケンシャルに呼び出されることを保証するため、Aff
をベースにしています。また、nodejsはrequest streamとresponse streamを1リクエストで扱いますが、それらを1つにまとめたHttp
型をもっています。
早い話、具体的な型定義はnewtype Handler a = Handler (ReaderT Http Aff a)
となっています。
サーバーを作成
まずはこちらを見てください。
server :: Effect Server server = createServer middleware
さて、Middleware
はHandler (Maybe ResponseBody) -> Handler (Maybe ResponseBody)
でした。最後のnext
には何が渡されるのでしょうか?
createServer
の処理の中で、最後のnext
には、404を返すだけのHandler
が渡されます。
つまり、どのミドルウェアの処理にも引っかからないと404を返すようになっています。
サーバーを起動
最後はさっきのサーバーを起動するだけでサーバー出来上がりです! かなり簡単ですね。
main :: Effect Unit main = server >>= listen opts opts :: ListenOptions opts = { hostname: "127.0.0.1" , port: 3000 , backlog: Nothing }
詳しくはサンプルコードを見るとよりわかりやすいかもしれません。
既存のミドルウェア
こちらに現在8個のミドルウェアができています。 Bucketchainはあくまでインターフェースで、これに則ってミドルウェアとしてライブラリやフレームワークをつくるという世界観なので、より具体例を見るのであれば、こちらをご参照ください。
久しぶりにPureScriptのパッケージを書いたりしてた
追記 本記事のconveyor向けパッケージはメンテされていません。ご注意ください。
しばらくPureScriptから離れていたが、 サーバー用にいくつかほしくなった仕組みがあったため、久しぶりにPureScript書いた。
Update
- purescript-crypto
- basic認証用にタイミングセーフな比較処理を追加
- その他、軽微な変更
New
-
- nodeバックエンド向けのベーシック認証用のヘルパ
purescript-conveyor-basic-auth
- 拙作のpurescript-conveyor向けのbasic認証をやってくれるミドルウェア的なやつ
-
- 拙作のpurescript-conveyor向けのヘルスチェック用のエンドポイントを生やしてくれるミドルウェア的なやつ
とりあえずライブラリを書く時はまだしばらくbowerを使っておくことにした。
そんなにPureScript忘れてなかった。
久しぶりにPursuit見たらサーバー向けっぽいパッケージが増えてた。
Pursuitに最新版があがってないパッケージがあった。node系のやつだったかな。
PureScriptは0.12以降であんまり動きがないように見えてたけど、マイルストーンを見た感じ、1.0に向けて頑張ってるっぽいですね。
parcel-plugin-build-hooksつくった
parcelで任意のビルドイベント(例えば、ビルド完了時、ビルド開始時など)でcliを叩く、などをやりたい。 この場合、parcelの生APIを用いれば上記の目的は達成できるが、これはparcelの生APIを使ってビルドスクリプトを書くことを意味する。 なるべくビルドスクリプトは用意したくない。
こういった気持ちが生まれたため、プラグインにしときました。
使い方
package.json
に任意のイベント時に叩きたいコマンドを書く。
{ "name": "your-app", "main": "index.js", "dependencies": { "parcel-plugin-build-hooks": "^1.0.0" }, "parcel-plugin-build-hooks": { "buildStart": "// Do something", "bundled": "// Do something", "buildEnd": "// Do something", "buildError": "// Do something" } }
以上。
フリーランスになって1年経った
気づいたら、フリーランスになってから1年経っていました。 社会に出る前からフリーランスになる可能性は高そうだなと思っていたものの、踏ん切りがつかなかった自分が1年フリーランスできたことに対して、昔の自分は驚く気がします。
フリーランスになって
フリーランスになる前は以下について心配していました。
- 実力的な意味で自分がやっていけるのか
- お金の交渉をできるのか
- 仕事は取ってこれるのか
- 限られた時間で成果を出せるのか
1については、厳密には他人が決めることなので正確なことは言えません。ですが、話している感触としてはやっていけていると勝手に思っています。 他のフリーランスを見ていると、やっていきかたは人によって様々で、得意分野に特化して技術的な意味で役に立っているパターンもあれば、普通に機能開発を手伝っているパターンもあります。他人がしたことで社員が喜んでいるのを見たりして、「こういうのが喜ぶのか。喜ばれる目的に対してコスパがいいので記憶に残しておこう。」など、うまくやっている人を見て私も学んでいます。フリーランスの方は持ってるスキルも色々な意味で様々なんですが、スキルが原因でクビにされてるのは「今のところ」は見たことがないです。
2については、自分の場合は意外と出来ました。出来たというよりは、堂々とほしい金額を言っただけで払ってもらえている、といったところです。 わたしはこの1年のうちに3社経験していて(いずれも準委任です)、その中には金がある企業全然ない企業両方含まれています。 その前提で、すべて言い値で通りました。 ほしい金額を言うことがまず大切だなということを痛感しています。
3については、仕事を取りに行かずに済んでいる、という状況です。私はサラリーマンとして3社経験しています。そしてその3社で知り合った方々も色々なところへ散っていってます。私はサラリーマン時代に真面目に働いていたおかげかこの状況下なおかげか知り合い経由でお誘いが断続的に来ます。中にはお誘いを断っても定期的に移る気がないか確認してくる人もありがたいことに存在しています。 知り合いが重要というのは本当でした。
4については、自分の中ではまだ最大限ではないなと思っています。 まず業務時間については、サラリーマンで言うところの残業はそのまま損失なので、現在では、それを1mmもやらないようにし、業務してるとき以外は業務に関することをなるべく考えないように徹するようになりました。 また、今は2社から仕事を受けていますが、業務内容もまるっきし違いますし、1週間のうちに業務が切り替わるのもすごいコンテキストスイッチが発生します。 これらの前提、且つ、単位時間を1週間とみなした場合、サラリーマンとやっていたときと比べて単位時間あたりのパフォーマンスが落ちている気はしています。
不安はある
やはり不安なのは、いずれ誘ってくれる人がいなくなったらどうしようというのは常に頭にあります。 なので、1社1社、誠実に働かないといけないなとたまに考えたりします。 いつまでできるのかはわからないですが、どこかに入社したいなと思うまではフリーランスを続けようと思います。