Google Docsみたいな共同編集Webサイトを作るライブラリ Yjs 初めの一歩 まずは動作させてみる

Yjs と聞いて、何を思い浮かべるでしょうか?
検索すると、〇〇先輩とか出てきますが、先輩ではありません。

↓これです。

A CRDT framework with a powerful abstraction of shared data
https://github.com/yjs/yjs/tree/master

CRDTできるフレームワークと書いてありますが、CRDTとは何かと言い出すと、Conflict-free replicated data typeの略で結構難しい話になります。
そこで、CRDTをすごく平たく言うと、Google Docsとか、MicrosoftのOffice365のExcelとか、AさんとBさんが同じExcelのシートを開いていても、共同で編集できますよね。あれがCRDTです。

そんな機能を実現させるためのライブラリです。

ベルリン在住のケビン・ヤーン(?)さんが作っているようです。
ありがとう、ケビンさん!

さて、まずはめっちゃ簡単に動作させてみます。

しかし、「Yjs sample」 とかググってみても、Reactを使ったりマイクラを使ったり、TODOアプリとかちょっと複雑なアプリが多く出てきます。
そういうのじゃなくって、「Hello World」的なことがまずは最初にしたい!という人いませんか?→はい、私です。
他にもそういう方がいるのではないかと思いまして、この記事を書きました。

灯台元暗しでYjsの公式サイトに「Hello World」的なサンプルがありました!

https://docs.yjs.dev/

import * as Y from 'yjs'

// Yjs documents are collections of
// shared objects that sync automatically.
const ydoc = new Y.Doc()
// Define a shared Y.Map instance
const ymap = ydoc.getMap()
ymap.set('keyA', 'valueA')

// Create another Yjs document (simulating a remote user)
// and create some conflicting changes
const ydocRemote = new Y.Doc()
const ymapRemote = ydocRemote.getMap()
ymapRemote.set('keyB', 'valueB')

// Merge changes from remote
const update = Y.encodeStateAsUpdate(ydocRemote)
Y.applyUpdate(ydoc, update)

// Observe that the changes have merged
console.log(ymap.toJSON()) // => { keyA: 'valueA', keyB: 'valueB' }

これを、index.mjs という名前で保存します。

PCにNode.jsはインストールされていますか?されていなければ、まずはNode.jsをインストールしてください。

Node.jsがインストールされていれば、次はYjsをインストールします。
私の開発環境はWindowsです。なのでコマンドプロンプトを開いて次のコマンドを実行します。

npm i yjs y-websocket

厳密にいうと、後半のy-websocketは今は必要なさそうですが、いずれ必要になりそうなので入れておきます。

インストールできましたね!

そしたら、さっき保存したindex.mjs をnodeコマンドで動作させます。

node index.mjs

すると、上記のスクショのように、サンプルコードの下記の部分が表示されます。

console.log(ymap.toJSON()) 
('keyA', 'valueA')

だったymap が 

('keyB', 'valueB')

という ymapRemote と統合されて

 { keyA: 'valueA', keyB: 'valueB' }

になったんですね~。

すごい!
もちろん、これだけではすごさは全く伝わらないと思うので、Yjsについては今後記事を書いていきたいと思います。

SourceTreeでAccessTokenを作ってGithubに接続できない

SourceTree Ver 3.3

実は半年ぐらい、下記のエラーが出て

git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks fetch --no-tags origin
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: Authentication failed for 'https://github.com/hogehoge'

SourceTreeでGithubに接続できなくて困っていました。

Githubがメールアカウントとパスワードではなく、Access Tokenというものを使ってしかGihutbクライアントからアクセスできなくなったのは有名な話ですが、下記などいろいろなサイトでやり方が紹介されているものの、

https://zenn.dev/koushikagawa/articles/3c35e503c8553a

https://syslog.life/2022/01/21/github-sourcetree-alignment-access-token/

上記のサイトのようにOauthにしてパスワードをトークンにしても、ベーシック認証にしてパスワードをアクセストークンにするなど、いろいろやってみてもダメでした。

SourceTreeをアンインストールしたりしてもダメだったので

「どうせ僕なんて…アクセストークンも使いこなせない人間なんだ…。」

とウジウジしながらコマンドプロンプトや他のGihutbクライアントを使う毎日でした。(>_<)

しかし、今日やっと解決しましたので、書いておきます!

こちら、SourceTree本家のサイトに書いてありましたね💦

Sourcetree ignores github token and throws 403 error

https://community.atlassian.com/t5/Sourcetree-questions/Sourcetree-ignores-github-token-and-throws-403-error/qaq-p/1778978#U1785059

ちゃんと英語のサイト読めよってことですね!

同じようなことに困っている方がいらっしゃると思うので、以下、やり方を書いておきます。

①右上の設定ボタンをクリックし、下記の「リモート」を表示させて、編集をクリックします。

②次の画面で、リモートの詳細設定という設定がありますが、ここのURL/パス欄に

次のように入れます。

https://<token>@<git_url>.git 

わかりづらいので解説すると、token が 123456 だとして、GithubのURLが https://github.com/hogehoge/hogeだとすると、

https://123456@github.com/hogehoge/hoge.git

と入れるということです。

すると、何と接続ができます。

ヤッター!!

新規のCloneするときも、

一番最初の 「元のパス/URL」 とある欄に、同じようにアクセストークンを含めたURLを入力します。

すると、接続できます。

ありがとう、世界!⊂(^-^)⊃ 吾妻山公園というところからの眺めです。

jest で vue のコンポーネントのメソッドをテストしたいが呼び出せない

jest 27.4.3
vue/test-utils 1.3.0
vue 2.5.2

すみませんが、jest 初心者です。

初心者らしく、初心者がハマりそうなポイントを書いておきます。

TimeTable.vue というコンポーネントがありまして、次のようにコンポーネントのテストを作ったりすると思いますが

/**
 * TimeTable.spec.js
 * @jest-environment jsdom
 */

import {createLocalVue, mount} from '@vue/test-utils'
import TimeTableVue from '../../../../../components/timeTable/templates/TimeTable'
import Vuex from 'vuex'  

 const localVue = createLocalVue()
  localVue.use(Vuex)

  let store

  const wrapper = mount(TimeTableVue, {
    stubs: ['font-awesome-icon'],
    propsData: {
      getServiceHandler: jest.fn(),
    },
    components: {},
    computed: {},
    store,
    localVue
  })

describe('text check', () => {
  it('should be some class', () => {
    expect(wrapper.find('.some_class').exists()).toBe(true)
  })
})

ここで、TimeTable.vue のメソッドに

// 略  
methods: {
    setDrivers (drivers) {
      this.drivers = drivers
    },
// 略

というメソッドがあった場合、テスト(TimeTable.spec.js)から

wrapper.setDrivers(drivers)

とやっても、

TypeError: setDrivers is not a function

みたいにメソッドが見つからないエラーになってしまいます。

これ、Vueのコンポーネントにアクセスする場合は、

wrapper.vm

を使わないとダメなんですね。

つまり、TimeTable.vue コンポーネントの中の setDrivers() にアクセスしたい場合は

wrapper.vm.setDrivers()

としないとダメです。

Vue Test Utilsの公式サイトのwrapperの説明に下記のようにありました。
https://v1.test-utils.vuejs.org/api/wrapper/#properties

———————————————————————-
# vm

Component (read-only): This is the Vue instance. You can access all the instance methods and properties of a vm

with wrapper.vm. This only exists on Vue component wrapper or HTMLElement binding Vue component wrapper.

———————————————————————-

findとか使う場合は wrapper 自体を使うので、間違えちゃいますよね!
(๑>◡<๑)

Chrome 開発者コンソールでマウスオーバーしたときや、クリックしたときのスタイルを検証したいけどマウスを離すと検証できないを解決する

これはですねー  いつも忘れるので書いておきます!

<a>とか<button>とか、:hover というのでマウスオーバーしたときだけスタイルを変更する、とかCSSでやりますよね?

しかし、そのスタイルが微妙だったりするときに、普通の要素だったら右クリックした開発者コンソールに行けばすぐ解決しますが、マウスオーバーしたときのスタイルを検証しようと思っても、開発者コンソールにマウスを持っていくとマウスオーバーしたときのスタイル見えないじゃん!
:hover のスタイルがわかんないじゃん!

ということになります。

そんな時は、Chromeの開発者コンソールでは、要素からのスタイルパネルの「フィルタ」という入力欄の右の

:hov

というところをクリックしてみましょう。

 下記の画像の赤丸で囲んだところです。

左で選択した要素を、強制的に :hover 状態にしたり、 :active状態にしたりできます!
ありがたや~。

ちなみに、この:hover とかは「疑似クラス」と呼びます。

javascript アロー関数のthis は普通の関数のthis とは違う話

ES2015

javascriptって難しいな~ と思う理由の一つに、スコープとか関数の定義の仕方が豊富すぎることがあります。

ある日、アロー関数のthisって普通の関数と違う?と思ったことがあるので書いておきます。アロー関数とは これ => を使った関数定義でfunction とか書かなくてもよい関数の定義の方法です。

   const o = {
       name: 'Hoge Tarou',
       greetName: function (){
           function greetPolite(){
               return 'Hello' + this.name //Helloしか表示されない
           };

           return greetPolite()
       }
   }

   console.log(o.greetName())

上記だと

 greetPolite()

の中で this.name で ‘Hoge Tarou’ を呼べません。

しかし、 下記のようにgreetPolite() をアロー関数にすると、これがthis.name で ‘Hoge Tarou’ を呼べ るんですね~。

   const o = {
       name: 'Hoge Tarou',
       greetName: function (){
           const greetPolite =() => {
               return 'Hello ' + this.name //Hello Hoge Tarouと表示される
           };

           return greetPolite()
       }
   }

   console.log(o.greetName())

アロー関数は他の関数と違い、thisの定義が違うんだそうです。

アロー関数式
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions

普通は、上記のような関数の中に関数を書いたりはあまりしないと思います💦。
ただ、コールバックとかの中で使う場合はあるのではないでしょうか?

私にとってのきっかけは、この前 axiosを使っていて次のようなところでつまづいたことでした。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title></title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta name="robots" content="noindex, nofollow">
    <meta name="googlebot" content="noindex, nofollow">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

</head>
<body>
<script>
    class Car {
        constructor(type, color) {
            this.type = type
            this.color = color
        }

        setColor(color) {
            this.color = color
        }

        execAxios() {
            axios.get('http://hogehoge.com?param=123')
                .then(function (response) {
                    this.setColor('red')
                }
                )
                .catch(function (error) {
                    //省略
                })
                .then(function () {
                    //省略
                });
        }

    }

    const car = new Car()
    car.execAxios()

</script>
</body>
</html>

上記は

 TypeError: this is undefined 

でエラーになります。(当然っちゃ当然なのですが)
上記のコードの下記の関数を

function (response) {
this.setColor('red')
}

アロー関数にするだけで

response => {
this.setColor('red')
}

this.setColorが呼べてひと段落しましたが、一時なんでアロー関数はOKで、普通の関数がダメなのかがわかりませんでした。

アロー関数とは、関数がはしょって記述できるだけではないんですね。便利に使える局面が多々ありそうです。

上記のアロー関数にした版のコード全文はこちら。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title></title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta name="robots" content="noindex, nofollow">
    <meta name="googlebot" content="noindex, nofollow">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

</head>
<body>
<script>
    class Car {
        constructor(type, color) {
            this.type = type
            this.color = color
        }

        setColor(color) {
            this.color = color
        }

        execAxios() {
            axios.get('http://localhost:8080/smart_location_admin/index.php?action=api/driver/getDrivers&company_id=\' + 9841 + \'&branch_id=\' + 10017')
                .then(
                 response => {
                     this.setColor('red')
                     console.log(this) //Object { type: undefined, color: "red" }が表示される
                 }
                )
                .catch(function (error) {
                    //省略
                })
                .then(function () {
                    //省略
                });
        }

    }

    const car = new Car()
    car.execAxios()

</script>
</body>
</html>