- 投稿日:2019-11-25T23:26:31+09:00
プライベートリポジトリをパスワードで限定公開するアプリを作った
GitHubのプライベートリポジトリを不特定多数に公開したい時ってありません? 私はあります、書類選考など。
不特定多数だから一人一人招待は無理だし、パスワード認証程度でいいんだけどなあと思いながら、
GitHubの設定でどうにかできないかと調べてみたんですが、ダメですね、なかったです。かなしいです。クソみたいなリポジトリなんてどうせ誰も見ないんだからパブリックにしちゃえば?と思われるかもしれません。
パブリックはなんか嫌だし、私が作ったものはクソじゃないし、百歩譲ってクソだったとしても自分のクソを全世界に公開する趣味はないです。なので作りました。他になさそうだったので。
http://35.233.244.144/
(クリックしても飛べない場合URLをコピーしてみてください)MineSweeper3Dのみパスワード公開してます。「unity」
これなに?
Webアプリケーションです。
使用技術は
フロント:React
サーバー:Golang echo
DB:Mongo
これはGCEのインスタンスの中のDockerで動いてます。
Webサービスではないので自分のリポジトリに適用させる場合はサーバー立ててCloneして云々が必要です。なぜWebサービスにしなかったのか
これはGitHubのアクセストークンを使用し、プライベートリポジトリを取得してきています。
悪意のある運営者であれば、サービスを使用した人のプライベートリポジトリを取得できます。
それって気持ち悪くない? 私だったら利用しません。なのでWebサービスにはしませんでした。どのように動いているのか
GitHub APIではアクセストークンを使用してリポジトリのファイルを取得できます。トークンは生成する必要があります。
https://api.github.com/repos/ユーザー名/リポジトリ/contents?access_token=トークン
みたいな。最初のディレクトリしか出ないので全て取得するにはディレクトリかを判別して再帰的に繰り返す必要があります。サーバーを立てる前にGolangで対象のリポジトリをクローリングするところから始まります。
./repo -repo yourrepo -expire 2020-02-02 -password yourpassword
こんなコマンドをサーバー内で実行します。
これはプロジェクトのファイル一覧を再帰的に取得してDBに入れています。あとはサーバーを立ててパスワード認証をして、認証に成功したらファイルを表示させてます。
ファイルは逐一GitHub APIを介してます。
用途としては、プライベートリポジトリの完全なミラーが目的ではなく、パスワード認証して限定公開が主目的だからです。
コマンド実行時のディレクトリ構造を保存し、そのパスをもとにファイルにアクセスしています。全体的に難しいことはしてません。
まとめ
本当に技術的に気になりましたらソースを見てください。
私のようにプライベートリポジトリを限定公開したいという人がいましたら、これを使うなり、使わなくともこれが参考になればと思い、記事をしたためました。
調べても同様のものが見つからなくて絶望した過去の私のような人間が一人でも救われるのであれば幸いです。
- 投稿日:2019-11-25T22:00:06+09:00
ReactでVimライクなInputを書いた
こんにちは
今年入社しました @tom-ock です。
昨日terraformの記事を上げてくれた @Sadalsuud さんと同じチームで開発しております。
担当ほどはっきりしたモノは今まだないですが、最近Reactが面白いです。自己紹介はこれくらいにして早速本題に。
TL;DR
Reactでviっぽいinputコンポーネントを作りました(type="text"です)。
実演
注意
- VimiumなどはOffにしてください
- 仕様上英語入力しか受け付けません
- 入力にはFocusする必要があるためクリックしてから入力してください
- 幅も有限なので、入力しすぎたらノーマルモードでdを押してください
- スマホからは操作できません!ごめんなさい
See the Pen Vinput by Tomoki Oke (@litalico-tomokioke) on CodePen.
(あるいは こちら(Github Pages))
実装概説
テキストエディタっぽいカーソルをどうしても表現したかったのですが、
inputを使用して実装する方法が思い浮かばなかったので今回は全てdivで実装し、
inputはhiddenでstateで渡すことにしました。stateはreducerで管理しています。
state. 内容 value 入力文字列 cursorIndex カーソルポジション mode モード 今回はノーマルモードとインサートモードの切り替え、文字列の入力、ノーマルモードでのいくつか移動を実装しました。
これらの3つの属性のstate + 入力されるキーから、次のstateが決定されるためそれをreducerに書きました。const normalReducer: React.Reducer<State, Action> = (state, action) => { switch (action.key) { case "d": { return { ...state, value: "", cursorIndex: getIndex.start(state) }; } case "i": { return { ...state, mode: "INSERT" }; } case "a": { return { ...state, mode: "INSERT", cursorIndex: getIndex.append(state) };至る所で移動する次のstateを計算するとごちゃごちゃしたので、カーソル移動とテキスト編集をそれぞれ別のファイルに分けて関数化したものをreducerでは使用しています。
const right: IndexGetter = ({ value, mode, cursorIndex }) => { if (value.length === 0 || cursorIndex !== value.length - 1) { return cursorIndex + 1; } else { return cursorIndex; } }; const left: IndexGetter = ({ value, mode, cursorIndex }) => { if (cursorIndex > 0) { return cursorIndex - 1; } else { return cursorIndex; } };const backspace: ValueGetter = ({ value, mode, cursorIndex }) => { return ( value.slice(0, cursorIndex - 1) + value.slice(cursorIndex, value.length) ); }; const insert: ValueGetter = ({ value, mode, cursorIndex, key }) => { return ( value.slice(0, cursorIndex) + key + value.slice(cursorIndex, value.length) ); };ここに苦労しました
ボックス形のCaret
Caret(入力時にカーソルの位置を示す部分)を操作するCSSは現在caret-colorが提供されています。
これは色の操作のみ操作できるプロパティで、viライクなボックス形のCaretは表現出来ません。
そこでハック感ありますが、inputタグは使わずにdivタグで入力フォームを表現する事にしました。キー入力をReducerのActionとしたかったのでonKeydownを使用した結果、英数字の入力のみ行える(日本語入力できない)仕様になったのはかなり心残りです。。
Reducer
カーソル位置は前述のcursorIndexで保持し、NORMALモードとINSERTモードのカーソル移動を実現しました。
入力値、カーソル位置、モードなどの状態は
これらの3つの属性のstate + 入力されるキーから、次のstateが決定されるためそれをreducerに書きました。
次のstateを前のstateから副作用のない関数として返せるような構造(getValue.ts, getIndex.ts)に分けています。
Vimならではのモーションとオペレーターのイメージで分けたからか、意外と見やすいReducerになった気がします。機能
そこまで多くないのであえて書きません。
READMEに書いてあるので、気になる方はこちらへ!
Github(https://github.com/ok8omk/Vinput)文字の入力をkeydownにしてしまったので日本語入力を受け付けられなかったり、
正規表現パワー足りず実装できてない部分あったり、
本当は複数行のテキストエリアを実装したかったり…
…色々やり残してるのでPR絶賛お待ちしています終わりに
ブラウザとかSlackとかで入力してる時に、全部Vimみたいにカーソル移動できたらいいのに!と思う瞬間が度々あるのが発端でした。(たまにありませんか?)
jsでCLIを表現するのは不毛な実装感がありますが、Reactとreducerのいい練習になりました。
npmで公開したので興味持って頂けた方は是非使って下さい!
npm(@ok8omk/vinput)課題だらけと思うのでissue大歓迎です、気長に直していくのでぜひお願いします
ReactをVimで書く記事はあっても、
ReactでVimを書く記事は見たことないなあと思って書いたので、
パイオニアであることを祈っております…明日は @litalico-takamasa-mizukami さんのAMP Storyです。
お楽しみに!
- 投稿日:2019-11-25T22:00:06+09:00
ReactでVimライク(H←L→)なInputを書いた
こんにちは
今年入社しました @tom-ock です。
昨日terraformの記事を上げてくれた @Sadalsuud さんと同じチームで開発しております。
担当ほどはっきりしたモノは今まだないですが、最近Reactが面白いです。自己紹介はこれくらいにして早速本題に。
TL;DR
Reactでviっぽいinputコンポーネントを作りました(type="text"です)。
NORMALモードでHで左に、Lで右にカーソルが移動します。実演
注意
- VimiumなどはOffにしてください
- 仕様上英語入力しか受け付けません
- 入力にはFocusする必要があるためクリックしてから入力してください
- 幅も有限なので、入力しすぎたらノーマルモードでdを押してください
- スマホからは操作できません!ごめんなさい
- Safariでの不具合が現在確認されています。ご了承ください。
See the Pen Vinput by Tomoki Oke (@litalico-tomokioke) on CodePen.
(あるいは こちら(Github Pages))
実装概説
テキストエディタっぽいカーソルをどうしても表現したかったのですが、
inputを使用して実装する方法が思い浮かばなかったので今回は全てdivで実装し、
inputはhiddenでstateで渡すことにしました。stateはreducerで管理しています。
state. 内容 value 入力文字列 cursorIndex カーソルポジション mode モード 今回はノーマルモードとインサートモードの切り替え、文字列の入力、ノーマルモードでのいくつか移動を実装しました。
これらの3つの属性のstate + 入力されるキーから、次のstateが決定されるためそれをreducerに書きました。const normalReducer: React.Reducer<State, Action> = (state, action) => { switch (action.key) { case "d": { return { ...state, value: "", cursorIndex: getIndex.start(state) }; } case "i": { return { ...state, mode: "INSERT" }; } case "a": { return { ...state, mode: "INSERT", cursorIndex: getIndex.append(state) };至る所で移動する次のstateを計算するとごちゃごちゃしたので、カーソル移動とテキスト編集をそれぞれ別のファイルに分けて関数化したものをreducerでは使用しています。
const right: IndexGetter = ({ value, mode, cursorIndex }) => { if (value.length === 0 || cursorIndex !== value.length - 1) { return cursorIndex + 1; } else { return cursorIndex; } }; const left: IndexGetter = ({ value, mode, cursorIndex }) => { if (cursorIndex > 0) { return cursorIndex - 1; } else { return cursorIndex; } };const backspace: ValueGetter = ({ value, mode, cursorIndex }) => { return ( value.slice(0, cursorIndex - 1) + value.slice(cursorIndex, value.length) ); }; const insert: ValueGetter = ({ value, mode, cursorIndex, key }) => { return ( value.slice(0, cursorIndex) + key + value.slice(cursorIndex, value.length) ); };ここに苦労しました
ボックス形のCaret
Caret(入力時にカーソルの位置を示す部分)を操作するCSSは現在caret-colorが提供されています。
これは色の操作のみ操作できるプロパティで、viライクなボックス形のCaretは表現出来ません。
そこでハック感ありますが、inputタグは使わずにdivタグで入力フォームを表現する事にしました。キー入力をReducerのActionとしたかったのでonKeydownを使用した結果、英数字の入力のみ行える(日本語入力できない)仕様になったのはかなり心残りです。。
Reducer
カーソル位置は前述のcursorIndexで保持し、NORMALモードとINSERTモードのカーソル移動を実現しました。
入力値、カーソル位置、モードなどの状態は
これらの3つの属性のstate + 入力されるキーから、次のstateが決定されるためそれをreducerに書きました。
次のstateを前のstateから副作用のない関数として返せるような構造(getValue.ts, getIndex.ts)に分けています。
Vimならではのモーションとオペレーターのイメージで分けたからか、意外と見やすいReducerになった気がします。機能
そこまで多くないのであえて書きません。
READMEに書いてあるので、気になる方はこちらへ!
Github(https://github.com/ok8omk/Vinput)文字の入力をkeydownにしてしまったので日本語入力を受け付けられなかったり、
正規表現パワー足りず実装できてない部分あったり、
本当は複数行のテキストエリアを実装したかったり…
…色々やり残してるのでPR絶賛お待ちしています終わりに
ブラウザとかSlackとかで入力してる時に、全部Vimみたいにカーソル移動できたらいいのに!と思う瞬間が度々あるのが発端でした。(たまにありませんか?)
jsでCLIを表現するのは不毛な実装感がありますが、Reactとreducerのいい練習になりました。
npmで公開したので興味持って頂けた方は是非使って下さい!
npm(@ok8omk/vinput)課題だらけと思うのでissue大歓迎です、気長に直していくのでぜひお願いします
ReactをVimで書く記事はあっても、
ReactでVimを書く記事は見たことないなあと思って書いたので、
パイオニアであることを祈っております…明日は @litalico-takamasa-mizukami さんのAMP Storyです。
お楽しみに!
- 投稿日:2019-11-25T21:33:39+09:00
React Hooksの魅力
ようこそ、React Hooks Advent Calendar 2019へ!まずは1日目ということで、React Hooksの魅力について語ってみます。
React Hooksの魅力
関数コンポーネントでも広がる機能性
もともとReactのコンポーネントはクラスコンポーネントしかなく、そして
render
だけで済むものが関数コンポーネントで書けるようになりました。ただ、関数コンポーネントを拡張していって、state
などが必要になると、改めてクラスコンポーネントに書き換える必要が出てしまいました1。React Hooksでは、関数コンポーネントのまま、
state
や更新時のフックを実現できるようになります。カスタムフックによるモジュール化
クラスコンポーネントでは、クラス内部に
componentDidMount
やcomponentDidUnmount
といったコールバックは1つしか作れなかったので、前準備と後始末を分けて書くしかない、ということがありました。React Hooksでは、コールバック類をいくつでも書けます。さらに、複数のHooksをまとめて呼び出すカスタムフックを作ることで、準備と後片付けをまとめて再利用することも可能としています。
粒度の細かな制御
クラスコンポーネントには、全体をメモ化して、
props
やstate
が変化しない限り再描画を抑える機能があります。また、componentDidUpdate
は更新のたびに実行されます。React Hooksの場合、
useMemo
を使えば「特定の変数群が変わらない限り」という条件でメモ化ができますし、useEffect
でも同様に「特定の変数群の変化」をきっかけとしてコールバックを実行できます。
React 16.12時点でも、
componentDidCatch
やgetSnapshotBeforeUpdate
といった一部のコールバックは関数コンポーネントで再現できません。 ↩
- 投稿日:2019-11-25T14:03:03+09:00
TypeScript 共有型の配列の型推論
TypeScript v3.6.3
では改善されている模様です。こちらに記述がなかったと思ったので
https://qiita.com/uhyo/items/6acb7f4ee73287d5dac0共有型(パイプ|で区切った指定した型のいずれかに一致する値の変数を代入できる型)
の配列の要素を取り出したとき型推論がうまくいかない。なんらかの変数に一旦代入しておかないといけない。
export type hoge = FOO | BAR; export typo FOO ={ kind :"FOO"; sawa : stinrg; } export type BAR={ kind: "BAR"; erika:string; } //NG if (hoge[0].kind==='FOO' as const) { } //OK const homare = hoge[0] if (homare.kind==='FOO' as const) }
- 投稿日:2019-11-25T12:08:24+09:00
Reactコンポーネントに状態を持たせる方法の比較
Reactのコンポーネントに状態を持たせる方法をいくつかがあるが以下を紹介する。
* ReactのuseState
* React Redux
* ReactのuseReducer
* React ReduxのHooksサンプルの内容は
input
でテキストを編集してinput
の中身を別の場所で表示する単純なもの。ReactのuseState
ReactのuseStateを使う。一番簡潔に書ける。一つのコンポーネント内で完結するのならば一番楽。
不便な点は複雑なコンポーネントになるとコールバックを子供の引数に渡してあちこち引き回すことになってややこしいこと。
const UseState: React.FC = () => { const [text, setText] = useState(""); return ( <div> value={text} <input type="text" value={text} onChange={event => setText(event.target.value)} /> </div> ); };React Redux
reduxを使った普通の書き方。グローバルに定義されたストアから状態を参照できる。状態の書き換えは
reducer
に集約される。お約束の定義がそれなりにあるのでこのサンプル程度のことをやるにはめんどくさい。あとコンポーネントのpropsをマッピングを定義するのがボイラープレートぽくて大量に書くと嫌になる。const SET_TEXT = "SET_TEXT"; interface SetTextAction { type: typeof SET_TEXT; payload: string; } type Action = SetTextAction; interface State { text: string; } const reducer = (state: State = { text: "" }, action: Action): State => { switch (action.type) { case "SET_TEXT": return { text: action.payload }; default: return state; } }; const store = createStore<State, Action, {}, {}>(reducer); interface AppStateProps { text: string; } interface AppDispatchProps { setText: (s: string) => void; } const App: React.FC<AppStateProps & AppDispatchProps> = props => { const { text, setText } = props; return ( <div> value={text} <input type="text" value={text} onChange={event => setText(event.target.value)} /> </div> ); }; export const DemoReduxReactRedux = () => { const RApp = connect( (initialState: State): AppStateProps => ({ text: initialState.text }), (dispatch: Dispatch<Action>): AppDispatchProps => ({ setText: (i: string) => dispatch({ type: SET_TEXT, payload: i }) }) )(App); return ( <Provider store={store}> <RApp /> </Provider> ); };ReactのuseRecuer
Reactの新しいAPIのHooksに導入されてuseReducerを使うやりかた。
子コンポーネントにコールバックを引き回す必要があるがdispatchだけを渡せばいいのでそこはuseStateに比べて簡素になった。
それでもdispatch引き回しがあるのは面倒だと思われる。const SET_TEXT = "SET_TEXT"; interface SetTextAction { type: typeof SET_TEXT; payload: string; } type Action = SetTextAction; interface State { text: string; } const reducer = (state: State, action: Action): State => { switch (action.type) { case "SET_TEXT": return { text: action.payload }; default: throw new Error("illegal action"); } }; const initialState: State = { text: "" }; export const DemoReduxUseReducer: React.FC = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> value={state.text} <input type="text" value={state.text} onChange={event => dispatch({ type: SET_TEXT, payload: event.target.value }) } /> </div> ); };React ReduxのHooks
react-reduxにもHooks APIを使う方法が導入された。
useSelector
とuseDispatch
を使う。useSelector
で状態を読み出しuseDispatch
で状態を書き換える。reducerなどは普通のreact-reduxと同じ。
connect
でpropsのマッピングがする必要がなくなったのは楽になった思う。const SET_TEXT = "SET_TEXT"; interface SetTextAction { type: typeof SET_TEXT; payload: string; } type Action = SetTextAction; interface State { text: string; } const reducer = (state: State = { text: "" }, action: Action): State => { switch (action.type) { case "SET_TEXT": return { text: action.payload }; default: return state; } }; const store = createStore<State, Action, {}, {}>(reducer); const App: React.FC = () => { const text = useSelector((state: State) => state.text); const dispatch = useDispatch(); return ( <div> value={text} <input type="text" value={text} onChange={event => dispatch({ type: SET_TEXT, payload: event.target.value }) } /> </div> ); }; export const DemoReduxReduxHooks = () => { return ( <Provider store={store}> <App /> </Provider> ); };まとめ
React ReduxのHooksを使うのが一番わかりやすいと思う。最初に一々マッピングを定義するのがボイラープレートぽくてめんどくさいし必要な状態が変わったときにコンポーネントの定義やマッピングの定義をいちいち書き換える手間が減ったのは楽になったように見える。
- 投稿日:2019-11-25T03:47:19+09:00
Material UI を使って出会う Warning: validateDOMNesting(...): <div> cannot appear as a descendant of
Material UI を使うと大量に発生する warning
Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.かなりうざいです。最新版にアップデートしても消えなくて辛い。
エラーの意味
DOM の Nesting には
じゃなくて div を使って という警告です。
毎度思うけど、React の警告厳しい。(でもReact好き)
React 的にそんなにまずいのでしょうかね。このエラーの意義はなんなんだろう?警告対象
return (<p> aaaaaa </p>)正しい
return (<div><p> aaaaaa </p></div>)Material UI を使うと結構出る
これは一例です。
component={"p"} を指定してたらだめ。
エラー
<Typography component={"p"} variant="h4">Jobs</Typography>修正コード
<Typography component={"div"} variant="h4">Jobs</Typography>検証環境
mui 4.7.0
以上