OmniAICreator/Qiita-1.07M huggingface dataset:
【テスト環境設定: Vitest】Vue3 + TypeScript + Vite

## はじめに
Vite上にVue3とTypeScriptの環境を構築し、JestをインストールしようとJestの公式ドキュメントを読んだところ、最新のVueへのJestのインストール方法がなく（最新版は本を買うように促された）ため、Vueの公式ドキュメントを読んだところ、Vitestというテスト用のライブラリがあると知り、インストールを行ってみました。

## 参考資料
https://ja.vuejs.org/guide/scaling-up/testing

## 環境
* Vue3
* TypeScript
* Vite

## テスト内容
App.vue内にVueというテキストが表示されていることをテストする

## 設定
```src/App.vue
<script setup lang="ts"></script>

<template>
  <div>
    <h1>Vite</h1>
  </div>
</template>

<style scoped></style>
```

### インストール
基本的には参考資料を元にインストールを進める
```sh
// プロジェクトに Vitest を追加する
npm install -D vitest happy-dom @testing-library/vue
```

```vite.config.ts
import { defineConfig } from "vite/config"; // 公式ドキュメントでは"vite"と書かれているが、"/config"を付けないとビルド時にエラーになる
import vue from "@vitejs/plugin-vue";

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
+  test: {
+    // jest ライクなグローバルテスト API を有効化
+    globals: true,
+    // happy-dom で DOM をシミュレーションします
+    // （peer dependency として happy-dom のインストールが必要です）
+    environment: "happy-dom",
  },
});
```

```tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ],
+  "compilerOptions": {
+    "types": ["vitest/globals"]
+  }
}
```

```src/__tests__/sample.test.ts
// テストコードの記述
import { describe, expect, test } from "vitest";
import { render } from "@testing-library/vue";
import "@testing-library/jest-dom";
import AppVue from "../App.vue";

describe("Viteというテキストが表示されている", () => {
  test("Viteというテキストが表示されている", () => {
    const { getByText } = render(AppVue);
    expect(getByText("Vite")).toBeInTheDocument();
  });
});
```

## エラー
上記の設定後、`npm test`を実行しましたが、
```
FAIL  src/__tests__/sample.test.ts > Viteというテキストが表示されている
Error: Invalid Chai property: toBeInTheDocument
```
このようなエラーが発生しました。

`toBeInTheDocument`メソッドを使えるように、下記コマンドで`jest-dom`をインストールします。

```sh
npm install -D @testing-library/jest-dom
```

`sample.test.ts`ファイルに`import "@testing-library/jest-dom";`を記述しjest-domをインポートします。

## 結果
再度`npm test`を実行すると、テストがPASSしました。

## まとめ
ReactではJestをインストールし、テスト環境を設定しましたが、VueではVitestを使用しました。

使い方はJestと変わらないようなので、Vitestを使用してテストを書いていこうと思います。
🌍 Terraform による AWSリソース管理 のファーストステップ

# 📌 概要

Terraform を使って Amazon Route 53 のホストゾーンをする方法 を解説します ✨

# 📌 main.tf

main.tf の作成がまだの方は以下の記事を参考にファイルを作成してください。

https://qiita.com/nobumory/items/624275ac0b08660a2637

# 📌 ディレクトリ構成

以下のようなディレクトリ構造でファイルを配置してください。

```
terraform-project/
│── main.tf
│── modules/
│   ├── route53/
│   │   ├── main.tf
```

# 📌 Route 53 のホストゾーンを作成

### main.tf

AWS のプロバイダーを設定し、VPC とセキュリティグループのモジュールを読み込む

```hcl

# 利用するリージョンを "ap-northeast-1"（東京）に指定
provider "aws" {
  region = "ap-northeast-1"
}

# Route 53 のモジュールを読み込む
module "route53" {
  source = "./route53"
}
```

### route53/mainf.tf

ホストゾーンを作成し、ホストゾーン の ID を出力します。

```hcl
# Route 53 のホストゾーンを作成
# "sandbox-terraform.com" というドメイン名のホストゾーンを管理
resource "aws_route53_zone" "zone" {
  name = "sandbox-terraform.com"
}

# 作成した Route 53 ホストゾーンの ID を出力

output "route53_zone_id" {
  value = aws_route53_zone.zone.zone_id
}
```

[参考リポジトリ]

https://gitlab.com/Morykun/sandbox-terraform

# 📌 実行

準備ができたらコマンド実行しましょう！

1. `terraform init`
2. `terraform plan`
3. `terraform apply`

Terraform関連のコマンドについては以下の記事を参考にしてください ☺️

https://qiita.com/nobumory/items/9f3c84f016fbf37363ed

# 📌 NSレコードの設定

ドメインの発行にお名前どっとこむを利用された方は以下の記事も見てみてくださいね 👋

https://qiita.com/nobumory/items/beb7a7c7f19e3c6bad16
LaravelのLog levelと記録されるファイルについて

# はじめに
Laravelに移行する作業をしていた際に、「Logのレベルにはどのような違いがあるのか？errorやalertはどんな場面で使うべきなのか？」や「`Log::warning()`を使用した場合、どのファイルにメッセージが出力されるのか？」といった疑問が出てきたので、調べた内容をまとめてみました。

# LaravelのLog levelとレベル感
 Laravelのドキュメントによると、Log levelはRFC5424に基づいているようです。そのページから抜粋するとこのようになっていました。
 ```md
 Severity
             Code

              0       Emergency: system is unusable
              1       Alert: action must be taken immediately
              2       Critical: critical conditions
              3       Error: error conditions
              4       Warning: warning conditions
              5       Notice: normal but significant condition
              6       Informational: informational messages
              7       Debug: debug-level messages
 ```
　では実際にどんな時にどのレベルでログを出せばいいのか？を調べてみると、こんな感じに分けられます。
 
| Level | 意味 | 例 |
| ---- | ---- | ---- |
| Emergency | システムが使用不可能 | サーバがダウンした、致命的なエラーが発生した |
| Alert | すぐに対処が必要 | DB接続が失敗した、重要なサービスが失敗した |
| Critical | 重大なエラーが発生した | アプリケーションの重要な機能が動作していない|
| Error | エラーが発生した | APIレスポンスエラー|
| Warning | 警告メッセージ | ディスク容量が少なくなっている |
| Notice | 通常の動作&通知するイベント| ユーザが新しいアカウントを作成した、メールが送信された |
| Informational | 動作の情報| アプリケーションの状態やプロセスの進行状況|
| Debug | デバッグ | 変数の値や関数の戻り値 |

# メッセージの出力先
　次にどのファイルにログが出力されるように設定しているのかを確認します。Laravelではlogging.phpにメッセージを出力するログファイル、ログのフォーマット、ログレベルなどを設定できます。
 例えば下のような設定であったとしたら、logging.phpにはalertレベルとinfoレベルのログファイルの設定しかされていません。では、`Log::warning();`をするとどのファイルに出力されるのでしょうか？

 ```php
 <?php

declare(strict_types=1);

return [
    'default' => env('LOG_CHANNEL', 'info'), 
    'channels' => [
        'info' => [
            'driver' => 'single',
            'path' => storage_path('logs/info.log'),
            'level' => 'info',
        ],
        'alert' => [
            'driver' => 'single',
            'path' => storage_path('logs/alert.log'),
            'level' => 'alert',
        ],
    ],
];
 ```
 この場合、デフォルトのチャンネルがinfo, そしてinfoチャンネルのレベルはinfoに設定されているので、info.logに出力されます。
  infoレベルの場合、info以上(info, notice, warning, error, critical, alert, emergency）のレベルのメッセージが記録されます。alert.logはalertレベル以上のメッセージしか記録されないので、`Log::warning()`のメッセージは記録されません。
 ```php
 'info' => [
            'driver' => 'single',
            'path' => storage_path('logs/info.log'),
            'level' => 'info',
        ],
 ```
`Log::debug()`をコードに仕込んでもどのファイルにも出力されない、ということですね...

# 最後に
もしかしたら設定次第ではどこにも出力されないLogが存在してるかも...?と思うと、もっとlogging.phpとLogのレベルに注意を払っていこうと感じました。
参考になれば幸いです🍎

# 参考
https://laravel.com/docs/11.x/logging

https://datatracker.ietf.org/doc/html/rfc5424
🌎 Terraform で S3 + DynamoDB を使った状態管理のシンプルな手順

# 📌 概要

Terraform の状態を **S3 + DynamoDB** で安全に管理する方法をまとめます😊

これを使えば、ローカルからでも、　どこか他のサーバーからでも同じ状態を共有して Terraform を実行できるようになります👌🏻

必須ではありませんが、チーム開発や複数環境での運用を考えるなら導入をおすすめします🔝

# 📌 事前に準備するもの

main.tf の作成がまだの方は以下の記事を参考にファイルを作成してください。

https://qiita.com/nobumory/items/624275ac0b08660a2637

# 📌 AWSソースの作成

Terraform の `backend "s3"` を使うために、まずは **S3 & DynamoDB** を手動で作成しよう。

### ✅ S3 バケットを作る

```sh
aws s3api create-bucket --bucket sandbox-terraform-mory --region ap-northeast-1 --create-bucket-configuration LocationConstraint=ap-northeast-1
```

`--bucket` の後ろのバケット名は任意で変更してください

#### **S3 のバージョン管理をONにする（バックアップ用）**

```sh
aws s3api put-bucket-versioning --bucket sandbox-terraform-mory --versioning-configuration Status=Enabled
```

`--bucket` の後ろのバケット名は任意で変更してください

### ✅ DynamoDB を作る（ロック管理用）

```sh
aws dynamodb create-table --table-name sandbox-terraform-mory --attribute-definitions AttributeName=LockID,AttributeType=S --key-schema AttributeName=LockID,KeyType=HASH   --billing-mode PAY_PER_REQUEST
```

`--table-name` の後ろのテーブル名は任意で変更してください

# 📌 コーディング

S3 & DynamoDB を作ったら、Terraform の maiin.tf の冒頭に以下のコードを追加しよう。

### ✅ `main.tf` に `backend` 設定を追加する

```hcl
terraform {
  backend "s3" {
    bucket         = "バケット名"
    key            = "terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "テーブル名"
  }
}

provider "aws" {
  region = "ap-northeast-1"
}
```

[参考リポジトリ]

https://gitlab.com/Morykun/sandbox-terraform

# 📌 コマンドの実行

### ✅ Terraform を初期化しよう！

```sh
terraform init
```

実行するとこんなログが出力されます。

```
Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v5.87.0...
- Installed hashicorp/aws v5.87.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```
このとき、以下のメッセージが出るので `yes` と入力しよう。

```plaintext
Do you want to copy existing state to the new backend?
Enter "yes" to copy and "no" to start with an empty state.
Enter a value: yes
```

### ✅ S3 に `.tfstate` が保存されたか確認しよう
```sh
aws s3 ls s3://sandbox-terraform-mory
```
✅ **成功するとこんな感じで表示されるよ！**
```plaintext
2024-02-09 12:00:00   5.4K terraform.tfstate
```
Difyの導入、およびローカルLLMをモデルプロバイダに設定する

## はじめに
この記事では、Difyをコンテナとして導入し、ローカルで動作するLLM（Large Language Model）をモデルプロバイダとして設定する方法を解説する。また、Difyでクエリとしてファイルを渡す設定についても触れる。

## Difyの導入

Difyを使用する際、最も簡単な方法はDockerコンテナを利用することである。以下の手順で導入する。

### 1. DockerとDocker Composeのインストール
Difyをコンテナとして動作させるには、あらかじめDockerとDocker Composeをインストールしておく必要がある。インストール方法は公式ドキュメントを参照する。

### 2. Difyコンテナの起動
以下のコマンドを使用してDifyを起動する。

```bash
git clone https://github.com/langgenius/dify.git
cd dify
docker-compose up -d
```


これで、Difyの各サービスが起動する。ブラウザで`http://localhost/install`にアクセスし、管理者アカウントの設定を行う。

## ローカルLLMをモデルプロバイダとして登録する

ローカルで稼働するOpenAI互換APIを持つLLMをDifyに登録する手順は以下の通りである。

1. **Difyの設定画面にアクセス**

Difyの管理画面で、左側のメニューから「設定」を選択し、「モデルプロバイダー」をクリックする。

2. **新しいモデルプロバイダの追加**

「OpenAI-API-compatible」を選択し、「Add model」をクリックする。

3. **モデル情報の入力**

以下の情報を入力する。

- **Model Name**: 任意のモデル名
- **API Key**: 必要に応じて入力（空欄でも可）
- **API endpoint URL**: ローカルLLMのエンドポイントURL（例: `http://host.docker.internal:3000/v1`）

`host.docker.internal`は、Dockerコンテナからホストマシンを参照するための特殊なホスト名である。これにより、コンテナ内からホスト上で稼働するLLMにアクセスできる。
逆に言うと、この設定を入れないとdifyコンテナ内部からローカルホスト上で動いている（今回の場合はopen-webuiコンテナが提供している）LLMサーバへの通信が通らない。

4. **モデルの保存**

入力が完了したら、「保存」をクリックしてモデルを登録する。
うまく通信できたら保存に成功する。

※ローカルホスト上のLLMサーバのAPIのエンドポイントのポート番号（今回の場合はopen-webuiをデフォルト設定で使用するので3000）については、ubuntuの場合はufwでも通信を許可しておく必要がある。

## Difyコンテナ設定の修正（`host.docker.internal`の有効化）

`host.docker.internal`を使用するためには、Dockerの設定を修正する必要がある。

`docker-compose.yml`ファイルを開き、`extra_hosts`セクションを追加して`host.docker.internal`を有効化する。これにより、コンテナ内からホストマシンのサービスにアクセスできるようになる。

具体的には以下のパスに格納されているdocker-compose.yamlファイルにおいて以下のようにAPIセクションの末尾にextra_hostsセクションを追記する。

dify/docker/docker-compose.yaml
```
services:
  api:
    # 既存の設定はそのまま
    extra_hosts:
      host.docker.internal: host-gateway
```
この状態で```docker compose up -d```を実行すれば、difyコンテナの内部からローカルホスト自身に向かって通信できるようになる。

## クエリとしてファイルを渡すための設定
Difyでクエリとしてファイルをアップロードする機能を有効化する手順は以下の通りである。

機能設定画面にアクセス
Difyの管理画面で、左側のメニューから「設定」を選択し、「機能」をクリックする。
ファイルアップロード機能の有効化
「ファイルアップロード」の項目を見つけ、「有効化」ボタンをクリックする。

※この設定がデフォルトではoffになっているので、llama-visionのような画像認識できるLLMを使おうとした時に画像を渡すことができず、困惑する
Difyでのワークフロー作成とAPI化及びハマりポイント

# 複数のLLMを活用したワークフローの作成手順

Difyを利用して複数のLLMを組み合わせたワークフローを作成する手順について解説する。本記事では、基本的な設定からAPIとしての利用方法、運用時の注意点までを網羅する。

## 1. Difyのインストール（Dockerを使用）

DifyはDockerコンテナとして導入するのが手っ取り早い。 
[参考文献](https://qiita.com/Olive14/items/ff57e74a5a2785082e85)

## 2. モデルプロバイダーへのローカルLLMの登録

ワークフローを作成する前に、モデルプロバイダーとしてローカルで動作するOpenAI互換APIサーバー（Open WebUI）を登録する。

1. **Difyにログインする**  
   Difyのダッシュボードにアクセスし、アカウントにログインする。

2. **モデルプロバイダーの設定を開く**  
   画面右上のアカウントアイコンをクリックし、「設定」を選択する。次に「モデルプロバイダー」タブを開く。

3. **OpenAI-API-Compatibleモデルを追加する**  
   「OpenAI-API-Compatible」の項目で「モデルを追加」をクリックする。

4. **モデル情報を入力する**  
   以下の情報を入力する。
   - **モデル名**: Open Webui側でpull済みのモデル名を選択（例: gemma2:latest）
   - **エンドポイント**: `http://host.docker.internal:3000/v1`
   - **APIキー**: Open WebUI側で設定したAPIキーを登録

5. **モデルを保存する**  
   入力内容を確認し、「保存」をクリックする。

これで、DifyからローカルのOpenAI互換APIサーバーにアクセスできるようになる。
※疎通やAPIキーの認証に失敗すると登録できない

## 3. 複数のLLMを活用したワークフローの作成手順

### ステップ1: 新しいワークフローを作成する

1. ダッシュボードから「ワークフロー」を選択し、「新しいワークフローを作成」をクリックする。
2. ワークフロー名と説明を入力する。

### ステップ2: ブロックを配置する

1. 必要なLLMブロックをドラッグアンドドロップで配置する。
2. 各ブロックに使用するモデルとパラメータを設定する。

### ステップ3: ブロック間を接続する

1. 各ブロックを線でつなぎ、データフローを定義する。
2. 条件分岐やループ処理が必要な場合は、対応するブロックを使用する。

## 4. 作成したワークフローの動作確認手順

### ステップ1: 入力値を確認する

1. ワークフローに適切な入力値を設定する。
2. 必要に応じてダミーデータを利用する。

### ステップ2: 実行する

1. ワークフローを実行し、ログを確認する。
2. 各ステップの出力内容を検証する。

### ステップ3: デバッグする

1. 出力結果に誤りがある場合、問題のあるブロックを特定する。
2. パラメータや条件を修正して再実行する。

## 5. Difyで作成したワークフローをAPIとして利用可能な状態にする

### ステップ1: API公開設定を行う

1. ワークフロー設定画面で「APIを有効化」にチェックを入れる。
2. 必要に応じて認証トークンを設定する。

### ステップ2: エンドポイントを確認する

1. APIエンドポイントURLをコピーする。
2. 入力パラメータと出力形式を確認する。

## 6. APIを公開する（有効化する）

1. ワークフローの「公開設定」を開く。
2. 「APIを有効化」にチェックを入れる。
3. 保存後、エンドポイントURLが生成される。

## 7. ワークフローの更新を反映する

1. ワークフローの編集を完了したら「保存」をクリックする。
2. APIとして利用している場合、更新内容が即時反映される。

## 8. ワークフローの「終了」ブロックで出力変数を指定していないため結果が返ってこない

- 出力が得られない場合、「終了」ブロックの設定を確認する。
- 出力変数が指定されているか確認し、必要なデータを明示的に設定する。

## 9. Difyワークフローの利点

- **メトリクス情報の閲覧**  
  ワークフローの実行状況や性能をリアルタイムで確認できる。
- **各ステップの処理内容を詳細に確認可能**  
  特にLLM系ブロックでは応答の全文が確認できるため、デバッグが容易である。
- **API利用時の詳細なログ追跡が可能**  
  ワークフローのログには各ステップの処理内容が記録されており、外部からAPIを利用している場合でもトラブルシューティングが簡単に行える。
個人的備忘録：それぞれのOSでコマンドを使い、MACアドレスを確認してアウトプットしてみた

## はじめに
ネットワーク機器には、固有の識別番号（48ビットの値）が割り当てられており、ネットワーク上でデバイスを特定するために使用されます。

:::note warn
***普段はあまり意識せずに使っていますが、実際に自分の端末にはどのMACアドレスが割り当てられているのか、この機会に確認してみます。***
:::

本内容は個人的な備忘録程度のものですが、どなたかの学習の参考になれば幸いです。

## 書こうと思ったきっかけ
普段何気なく使っているパソコンのMACアドレスについて、一度確認してみたいと思いました。

以前、IPアドレスについてはコマンドの結果をまとめたことがありましたが、**MACアドレスについては整理したことがなかったため、この機会にまとめることにしました。**

https://qiita.com/free-honda/items/cf5390dffb0732d7d96f

:::note info
**実際の業務でも使用するコマンドを使って確認していきますので、必要に応じて参考にしてください。**
:::

## そもそも、MACアドレスとは？
MACアドレスとは、ネットワーク機器に割り当てられる固有の識別番号であり、48ビットの値で構成されます。

![Screenshot 2025-02-09 at 19.34.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/dc44cf53-2ed6-3cea-8a98-7c7e7e5d4d97.png)
引用画像：https://shinmeisha.co.jp/newsroom/2020/03/17/mac-%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9media-access-control%E3%81%A8%E3%81%AF/

例えば、「`00:1A:2B:3C:4D:5E`」のような形式で表されます。このアドレスは、ネットワーク上でデバイスを識別するために使用され、通信の際に重要な役割を果たします。

## MACアドレスとIPアドレスの違い
私もITの学習を始めた頃は、MACアドレスとIPアドレスの違いをうまく言語化できない部分がありました。

***そこで、簡単に表にまとめてみましたので、参考にしてください。***

| 項目          | MACアドレス                     | IPアドレス                      |
|--------------|--------------------------------|--------------------------------|
| **役割**      | 機器の識別                      | ネットワーク上の位置識別          |
| **変更可能性** | 基本変更不可（偽装は可能）        | 動的・静的で変更可能              |
| **使用範囲**   | ローカルネットワーク内            | グローバルネットワーク対応        |

## 実際に確認してみた
ここでは、自宅のLinux、Windows、MacBookを使って、それぞれのMACアドレスを確認していきます。

:::note info
***MACアドレスの確認方法はいくつかありますが、今回はコマンドを使用して確認します。***
:::

### 各OSでのMACアドレス確認コマンド

**Linuxの場合**

```sh
ip a | grep ether
```

**実際のコマンド結果**

![Screenshot 2025-02-09 at 19.45.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/d6314f6a-3f42-21ae-de10-d196f6a5f2c2.png)

**Windowsの場合**

```cmd
getmac
```

**実際のコマンド結果**

![Screenshot 2025-02-09 at 19.50.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/110c3f11-0a6e-c67f-ec90-a39142a0feb4.png)

**Windows Serverの場合**

```cmd
getmac
```

**実際のコマンド結果**

![Screenshot 2025-02-09 at 20.00.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/6e6ca6f4-e8ba-b870-64fe-73353abfd6f6.png)

**MacBook（macOS）の場合**

```sh
ifconfig | grep ether
```

**実際のコマンド結果**

```sh
 ~/Desktop   ifconfig | grep ether
	ether xx:xx:xx:xx:xx:xx
	ether xx:xx:xx:xx:xx:xx
```

***これらのコマンドを使えば、各OSでMACアドレス（xxxに置き換え済み）を簡単に確認できます！***

## まとめ
読んでいただきありがとうございました。今回は基本的な内容をまとめましたが、私自身にとっても良い復習となりました。

:::note warn
***今後も基礎的な内容を積極的にまとめていきたいと思っています。***
:::

なお、本記事の内容は個人の備忘録として記載していますので、その点ご了承ください。

## 参考文献

https://shinmeisha.co.jp/newsroom/2020/03/17/mac-%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9media-access-control%E3%81%A8%E3%81%AF/
環境構築 Mac M2にJavaをインストールしVSCodeで使用するまで

## はじめに
普段はVSCodeを使用して開発をしているので、JavaもVSCodeで使用できるように環境構築して行こうと思います。

私の環境は MacOS M2 です。

## 手順
### 1. JDK（Java Development Kit）のインストーラをダウンロード
   Javaの開発に必要なソフトウェアのパッケージです。
   以下Oracle公式からダウンロードできます。
   https://www.oracle.com/java/technologies/downloads/

   ここでは JDK 21 の macOS を選択して、Mac のプロセッサが Apple の場合は ARM64 DMG Installer を選択します。
   ![スクリーンショット 2025-02-09 19.48.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813857/27f4819c-5d11-4694-2b97-ba86076016d4.png)
    インストーラを起動させて進めていきます。
    続けるを押し、どんどん進めたらインストールできます。
    ![スクリーンショット 2025-02-09 19.52.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813857/a3d5a5a8-0cce-821b-d942-b0676c826198.png)



   
### 2. JDKがインストールされているか確認します

ターミナルを開いて
    
```bash
javac -version
```
と入力します
```bash
javac 21.0.6
```
このようにバージョンが表示されていれば無事にインストールできています。
    
### 3. VScodeを開き、拡張機能のExtension Pack for Javaをインストール
VScodeの拡張機能の検索バーで```java```と入力すれば以下のようなコーヒーカップのアイコンの```Extension Pack for Java```があるのでインストールします。
![スクリーンショット 2025-02-09 20.00.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813857/a77c5631-a590-db77-20bd-3983312ee09e.png)
インストールが完了したらvscodeを再起動し、先ほどのプラグインを有効化する

### 4. vscodeを開き、Hello.javaファイルを作成
私の場合はJavaSampleというディレクトリを作成し、その下にHello.javaを作成しました。
```bash
.
└── JavaSample
    └── Hello.java
```
Hello.javaの中身はこう書きます
```java
package JavaSample;

public class Hello {
    public static void main(String[] arg) {
        System.out.println("Hello!");
    }
}
```
:::note warn
注意
package名とディレクトリ名を合わせる。
クラス名とファイル名を合わせるように気をつける。
:::

### 5. クラス名の下に表示されるRunをクリックすると、実行結果がコンソールに表示されます
![スクリーンショット 2025-02-09 20.18.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813857/c1c16c5c-0cbe-2484-e5b3-9700c704e8d7.png)

Runを押して```Hello!```とターミナルに表示されていれば成功です。
![スクリーンショット 2025-02-09 20.19.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813857/9cf4e6bf-ae89-8b24-df72-0047f00194b9.png)

お疲れ様でした！
[PowerApps]ユーザー定義関数（UDF）が使用できるようになった

# 背景
PowerAppsで関数（PowerFx）を実装しているとき、**共通関数**を作成したくなります。そこで、2025年入ってから**ユーザー定義関数**を定義できるといううれしいお知らせがあったので、手順を記事に残しておきます。

# 設定
Power Apps Studioで、**設定**>**更新**>**試験段階**>**ユーザー定義関数**をONにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/2bcfa8b3-11bd-331f-5da5-a4033a9a9347.png)

# 関数定義実装
**Apps**>**Formulas**で関数を定義する。
```
$定義関数名$(引数変数:引数型):戻り値型 = {$処理$;};
```
```
IsWeekEnd(d:Date):Boolean = {If(Weekday(d) = 7 || Weekday(d) = 1, true, false);};
```
日付を渡し、土曜または日曜か判定した結果を返す関数を共通関数として定義する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/c9cf5099-d314-fad9-860c-cea82cad95ef.png)


# 関数定義を使った処理実装例
**ボタンコントロール**>**OnSelect**に上記で定義した関数を実装してみました。
``` 
If(IsWeekEnd(DatePicker1.SelectedDate),Notify("土日です。"),Notify("平日です。"));
```
## 動作確認-平日
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/29c19caf-14fa-9de3-39c8-8926677faa6e.png)
## 動作確認-土日
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/36384d7b-f796-4bf1-4b00-ac16e9e93ccb.png)

# プラスα
## 戻り値なし関数
**:Void**をつけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/c1c85aa9-92b5-2a9a-5ed3-2d193d694264.png)

## 複数関数をユーザー定義関数に組み込み
**ユーザー定義した関数**を**別のユーザー定義関数の処理に組み込む**ことも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987347/ce746309-e222-497b-c7a2-3a84ef164545.png)

# まとめ
**Saas系のサービスは特に変化が速いため、日々アップデート情報をチェックしていきたい**と考えております。
**便利な機能が出てきたら、普段の開発に取り込んでいきたい**と考えております。
この記事が皆さんの役に立てば幸いです！
疑問点何かありましたら、コメントいただけると幸いです。
記事をご覧いただきありがとうございます。
安全なWebアプリケーションの作り方 第2版 仮想マシンセットアップ(Intel Mac)

## 概要
安全なWebアプリケーションの作り方 第2版 
仮想マシンセットアップのホストネットワーク設定部分で少し詰まったので、同じような境遇の方の一助になれば幸いです。
## バージョン
Mac: Ventura 13.4
VirtualBox: 7.0.24
## 内容
手順に従って、virtualboxをインストール

![スクリーンショット 2025-02-09 19.31.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537995/b1414a1e-315a-5d77-b32c-b82814683383.png)
しかし、ホストネットワークタブが見当たらずネットワークの設定ができない、、、
↓
ダウンロードするvirtualboxのバージョンを下げることで無事解決
https://www.virtualbox.org/wiki/Download_Old_Builds
こちらから7.0系をインストールして、
「ツール」のハンバーガーメニュー →　ネットワークから設定可能
![スクリーンショット 2025-02-09 19.38.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537995/07b1cf68-afb9-bf1c-2197-bba40b2a0b43.png)
ただ、ここでは特になにも変更する必要はなかった。

その後手順を進めていき、仮想マシンをインストールするときに
「ホストオンリーアダプター[廃止予定]」 →　「ホストオンリーネットワーク」
に変更する必要があり。
![スクリーンショット 2025-02-09 19.04.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537995/570d014e-6b5e-520b-591b-b042cd8deb5f.png)

pingによる疎通確認も取れたのでこの手順で問題ないかと。


virtualboxのアンインストールはこちらを参考にしましたが、関連ファイルの削除はしていないです。
https://qiita.com/miriwo/items/ce29e14a87e847a6239a
【Jest × react-testing-library】toBeInTheDocument()のエラーとgetAllByTestIdの使い方

# はじめに
`Next.js`で`React Testing Library`の`toBeInTheDocument()`を使用する際に発生したエラーについてまとめました。

:::note warn
***この記事は<font color="Red">個人的なアウトプット</font>を目的として作成したものです。そのため、誤った情報や不足している内容が含まれている可能性があります。もし間違いや気になる点がございましたら、ぜひご指摘いただけますと幸いです***。
:::


# 問題
取得したデータにタイトルがあることを確認するためのテストを実装しましたが、以下のエラーが発生しました。

```bash
Error: expect(received).toBeInTheDocument()

received value must be an HTMLElement or an SVGElement.
Received has type:  array
```
***該当のコード***
```ts
  it("タイトルがあること", async () => {
    render(<ArticleList />);

    await waitFor(() => {
      expect(global.fetch).toHaveBeenCalledTimes(1);
    });

    await waitFor(() => {
      expect(screen.getAllByTestId("title")).toBeInTheDocument();
    });
  });
```

# 原因
`getAllByTestId()`は 該当する要素を配列として返すため、`toBeInTheDocument()`を適用できないことが原因です。

# 解決方法
配列の要素数を確認するために`toHaveLength()`を使用すると、エラーを回避できます。

```ts
  it("タイトルがあること", async () => {
    render(<ArticleList />);

    await waitFor(() => {
      expect(global.fetch).toHaveBeenCalledTimes(1);
    });

    await waitFor(() => {
      expect(screen.getAllByTestId("title")).toHaveLength(2);
    });
  });
```
`toHaveLength()`を使用すると、要素の数が期待通りかを確認できます。

# 終わりに
これからも`React Testing Library`のメソッドの使い分けを学習していきたいと思います。

# 参考

https://stackoverflow.com/questions/68943625/found-multiple-elements-error-in-react-testing-library
「エンジニアリングマネージャーの仕事」を読んで　その3

## はじめに
James Stanier著「エンジニアリングマネージャーの仕事」を読んで私が印象に残ったことをメモがわりに、少しずつアウトプットします。

https://www.oreilly.co.jp/books/9784873119946/

## 2章 まずは自分を管理しよう
### 2.2　活動を分類して生産性を高めるには
1エンジニア時代と違い、多くの人と関わり、多数の小さなタスクと向き合い、1日中コンテキストスイッチが発生して、生産性を感じることが難しいというのは分かりみが深い。
しかし、それぞれの活動を4つのバケツに分類することで、生産的と感じることができるそうな。

#### 情報収集
適切な意思決定をするための知識ベースの糧となる活動
正式なプロセスはなくいつでもどこでも起こり得る。情報収集をしたいと思うことが大切。
- 😟 あらゆるところから自然と情報が入ってくるがために受け身になってるかもなぁ。
#### 意思決定
マネージャーが担うべき最も大切な仕事の１つ。
休暇申請の承認など小さなものから、人の採用など大きなものまで様々あるが、決定には細心の注意を払うとともに結果に責任を持つこと。
- 🤔 「細心の注意を払うこと」≠「時間をかけること」だと思う。そして結果に責任というのは、成功を確約するものではなく（そんなの無理）、結果のアウトカムから逃げないということだと認識した。
#### ナッジング
議論に対して自身の観点を提供することで決定に影響を与えること。
自身が意思決定を下す役割ではなくとも。
- 🤔 これは無意識だったので気を付けるようにしよう。それが必要な場面ではしかるべきところで発言しておくべきだし、そうでない時は不用意な発言をしないというのも大事なのだろう。
#### ロールモデル
物事をきちんと実行し、言うべきことを言うこと
いちばん良い方法はスタッフや同僚に実例で示すこと
- 😟 「やってみせ・・」の山本五十六メソッドと同じだな。そういう意味では今年はアウトプットをしっかりやっていきたい。
---
なるほどなぁ、こうやって分類することで、普段やっている雑多なことが意味づけられ、「作業」ではなく「仕事」になる。
自分を励まし勇気づけることにつながるのかもしれない。
ハンズオン記事の書き方テンプレート【自分用】

:::note info
使えそうだと思ったら、マネして構いません。
例として「JavaScriptで作るTODOアプリ」を考えて載せました。
:::

## 完成イメージ

:::note info
完成した画面の動画や画像を添付する。フローチャートなどでも良い。少し複雑なものなら仕様もここに記載する。
:::

> HTMLとJavaScriptを使ってシンプルなTODOアプリを作成する。
> TODOの追加ができ、TODOをメモすることができるアプリ。
> 
> ![javascript-todo-sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473780/15042ff4-4529-f2e0-5a6e-fee3d88dfb3f.gif)


## 概要

:::note info
基本的な情報はここに記載する。
:::

> | 動作環境 | macOS(M1) |
> | --- | --- |
> | 使用技術 | JavaScript、HTML |
> | 作業時間 | 5分 |


## 技術解説

:::note info
メインで使う技術の解説はここに記載する。記載しなくても構わない。
:::

> ### JavaScriptとは
> 
> - 主にWeb開発で使用されるプログラミング言語
> - 「JavaScript」と書いて「ジャバスクリプト」と読む
> - テキストエディタとブラウザがあればすぐに開発可能

## 事前準備

:::note info
どんなツールが必要で、どんなバージョンのものが必要かはここに記載する。
:::

> ### テキストエディタを用意
> 
> [Visual Studio Code](https://code.visualstudio.com/Download)でインストーラーをダウンロードし、インストーラーを起動しアプリをインストールする
> 
> ### ブラウザを用意
> 
> [Google Chrome](https://www.google.com/intl/ja_jp/chrome/)でインストーラーをダウンロードし、インストーラーを起動しアプリをインストールする


## 手順

:::note info
行った操作は全て記載する。必ず動作が確認できたコードを載せる。必要であれば画像も載せる。
:::
 
> ### プロジェクト作成
> 
> ```bash
> $ mkdir todo-app
> ```
> 
> ### プロジェクトを開く
> 
> VSCodeでプロジェクトを開く。
> 以降の作業は、todo-appをカレントディレクトリとする。
> 
> ### index.htmlの記述
> 
> index.htmlを作成し、以下のように記述する
> 
> ```html:index.html
> <!DOCTYPE html>
> <html lang="ja">
>   <head>
>     <meta charset="UTF-8" />
>     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
>     <title>TODO List</title>
>   </head>
>   <body>
>     <div>
>       <input type="text" id="title" />
>       <button type="button" onClick="addTodo()">追加</button>
>     </div>
>     <ul id="todos"></ul>
>     <script src="index.js"></script>
>   </body>
> </html>
> ```
> 
> ### index.jsの記述
> 
> index.jsを作成し、以下のように記述する
> 
> ```javascript:index.js
> function addTodo() {
>   const title = document.getElementById('title');
>   const todos = document.getElementById('todos');
> 
>   if (title.value === '') return;
> 
>   todos.innerHTML += `<li>${title.value}</li>`;
> 
>   title.value = '';
> }
> ```
> 
> ### 動作確認
> 
> Chromeでindex.htmlを開く。
> 完成イメージのように追加ができるはず。


## まとめ

:::note info
最終的な全体コード及びディレクトリ構成を記載する。行ったこと、学べたことを総括しても良い。
:::

> 最終ディレクトリ構成は以下のようになる。
> 
> ```plaintext
> todo-app/
> ├── index.html
> └── index.js
> ```
> 
> <details><summary>全体コード</summary>
> 
> ```html:index.html
> <!DOCTYPE html>
> <html lang="ja">
>   <head>
>     <meta charset="UTF-8" />
>     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
>     <title>TODO List</title>
>   </head>
>   <body>
>     <div>
>       <input type="text" id="title" />
>       <button type="button" onClick="addTodo()">追加</button>
>     </div>
>     <ul id="todos"></ul>
>     <script src="index.js"></script>
>   </body>
> </html>
> ```
> 
> ```javascript:index.js
> function addTodo() {
>   const title = document.getElementById('title');
>   const todos = document.getElementById('todos');
> 
>   if (title.value === '') return;
> 
>   todos.innerHTML += `<li>${title.value}</li>`;
> 
>   title.value = '';
> }
> ```
> 
> </details>
今週の学習記録（2025/02/02～2025/02/08）

## 🔍 学習内容
- **学習テーマ**: TypeScript, React, LPIC-Level1
- **使用した教材**: CodeLesson, Qiita, YouTubeなど

## ✏️ 学んだこと
### 主なポイント
- DOM操作
- 型の概念（TypeScript）

## 💡 学び・反省点
### 学び
- unknownは方が不明な場合に使用する。
- Conditional Typesは型における条件分岐のこと
- infer は型推論を行うためのキーワードで、Conditional Types の中で使う。
- Exclude<T, U>はTとUの共通部分を取り除く（対象差集合）。
- isはunknown 型や、any 型、Union 型の型の絞り込みができる。
- ESlintはJSファイルを編集するうえで、ルールを設定することができる
- compomentsを使用することでパーツを再利用することができる。

### 反省点
- 1日の学習時間が少ない日が多かった。 


## 📆 次週の予定
### 目標
- Reactの学習を可能な限り進める。
- 最低でも平日1時間、休日4時間を目処に学習できるように努める。

### 行動計画
- 通退勤時間も積極的に学習する。
- 学習前に5分程度の運動を挟む
- 休日だからといって気を緩めすぎない。

## 🏄‍♂️所感
　今回でTypeScriptの学習を完了させ、Reactの学習に入ることができました。Reactはまだ2日しか学習していませんが非常に興味深くもっともっと学習したいと思いました。やはり、HTMLだけだと似たようなパーツはコピペする必要があったので、それをコンポーネントとして分類分けできるのは非常に感動しました。  
　また、学習前に軽めの運動を挟むと学習中の集中度合いが高くなった気がするので、今後も継続していきたいと思います。休日の学習時間が相変わらず少ないので、この運動習慣を続け、学習時間を向上させたいと思います。
DMARCレポートをPOWERDMARCとValimail Monitorで可視化する

所有している複数のドメイン宛のメールを、Google WorkspaceやMicrosoft 365で送受信して、それぞれSPF/DKIM/DMARCの設定をしています。こうすると、各ドメインのDMARCレポートをメールで頻繁に受け取ることになりますが、添付されてくるXMLファイルをいちいち開封して中身を見るのが苦痛になってきました。

そこで、DMARCレポートを無視せずに確認作業の省力化を図るために、DMARCレポートの可視化ツールを使って、週一程度の頻度でその情報を見る運用とすることにしました。

クラウドベースの可視化ツールは、ネットの情報を確認すると、定番と言えそうなものがいくつかでてきたようです。その中から[POWERDMARC](https://powerdmarc.com/ja/)と[Valimail Monitor](https://www.valimail.com/products/monitor/)を選んで試してみました。

# DMARCレポート可視化ツールの仕組み
今回試した2種類のDMARCレポート可視化ツールの仕組みは単純です。DMARCレポートを受信するメールアドレスに各ツールが用意したメールアドレスを追加することで、DMARCレポートを当該可視化ツールの環境にも飛ばして、それを解析してもらいます。

DMARCレポートには「rua（集約、集計）レポート」と「ruf（失敗、フォレンジック）レポート」の2種類がありますが、POWERDMARCではrua/rufの両方、Valimail Monitorではruaのみを受け取る仕様でした。

実際に可視化ツールにDMARCレポートを送信するには、DNSサーバにて各ドメインの情報を変更します。具体的には「_dmarc.ドメイン名」のTXTレコード値を変更して、rua 及び ruf に可視化ツールのメールアドレスを追加するだけです。

# POWERDMARCは日本語対応で見やすいが、複数ドメインを管理するには有償版が必要
使い勝手や素人でも見やすい・使いやすいという観点では、POWERDMARCの方が良いと思いました。ただし、無償で使えるのは1ドメインのみでデータ保存期間も短いので、ちゃんと運用するには有償版が必須となります。

また、有償版でもすぐに使い始められる「ベーシック」は月額8ドルで5ドメインまでしか対応できず、それ以上は個別見積りが必要な「エンタープライズ」になってしまいます。より多くのドメインを管理できる安価な契約プランが望まれます。

とりあえずは、主に使っているドメインを5つ以内に絞って、ベーシック版で使ってみることにしました。

# Valimail Monitorは無償版でも多数のドメインが管理できる
一方、Valimail Monitorは、英語版の画面しかなく、素っ気ない見た目でとっつきにくい感じがしますが、無償版でもドメイン数の制限がないため、多数のドメインを管理したいというニーズには合っていると思いました。有償版にすると、分析機能などが使えるようになるので、それらの必要性を感じるようになったら、有償版に切り換えようかと考えています。

# DMARC可視化ツールを使うと、DMARC設定の間違いに気づける
今回、DMARC可視化ツールを使い始めたところ、DMARC設定がいくつか間違えていたことにも気づけました。DMARCの設定を数年前に始めたころには、Google Admin Toolboxの[Check MX](https://toolbox.googleapps.com/apps/checkmx/)を使って設定の確認をしていたのですが、最近は正しくDMARCの設定をしていてもエラーだと判定されるようになって、ツールとして使い物にならない状況でした。

一方、POWERDMARCやValimail Monitorでは、可視化対象のドメインを設定すると、そのドメインのSPF/DKIM/DMARCの設定が正しくできているかをチェックしてくれて便利でした。

特に、DKIMの設定については、DKIMで使う鍵長が長くなると、AWSのRoute53 でDKIMのレコードを設定する際に、失敗しやすい（公開鍵が途中で途切れてしまう）ので注意が必要です。

また、DMARCの設定も、p（ポリシー）パラメータをnoneのままにしていたり、pct（ポリシーを適用する割合）パラメータを50(%)のまま運用を続けていたケースが見つけられました。
この辺りを可視化ツールで警告してもらえると、忘れずにp=quarantine（隔離）/p=reject（拒否）やpct=100（すべてのメールに適用）まで設定できるようになりました。

# DMARCレポート可視化ツールはまだ黎明期
電子メールにDMARCが必須となる中、適切な運用を行うにはDMARCレポート可視化ツールも管理者側では必須となっていくことでしょう。今回使った2種類のツールも、まだ改善の余地はあるので、今後の成熟化とコスト低減が望まれます。

特に、メールサービスを提供している大手クラウド事業者（GoogleやMicrosoftを含む）は、自らのメールサービスの付加機能として、DMARC可視化ツールを提供すべきではないでしょうか。
シェルスクリプトが顕著に遅い実行速度となる場合があるようです（macOS）

こんにちは。
下記のシェルスクリプト```cycle_graph.sh```（whileループで回す）を macOS 上で実行すると顕著に遅いことに気がつきました。Linux 上ではそのような現象は見られませんでした。

#### macOS

```console
$ uname -s -r -m
Darwin 24.3.0 arm64
$ cat cycle_graph.sh
#!/bin/sh
n=$1  # positive integer
edge_length=1
i=0
while [ $i -lt "$n" ]; do
  i_next=$((i+1))
  echo "$i,$((i_next%n)),$edge_length"
  i=$i_next
done
$
$ for n in 400000 200000; do hyperfine --warmup 1 './cycle_graph.sh '$n' >/dev/null'; done
Benchmark 1: ./cycle_graph.sh 400000 >/dev/null
  Time (mean ± σ):      2.024 s ±  0.012 s    [User: 1.861 s, System: 0.160 s]
  Range (min … max):    2.006 s …  2.044 s    10 runs
 
Benchmark 1: ./cycle_graph.sh 200000 >/dev/null
  Time (mean ± σ):      1.033 s ±  0.009 s    [User: 0.949 s, System: 0.081 s]
  Range (min … max):    1.022 s …  1.048 s    10 runs

$
$ cat cycle_graph_awk.sh
#!/bin/sh
n=$1  # positive integer
edge_length=1
seq $n | awk -v n=$n -v e=$edge_length '{printf("%d,%d,%d\n",$1-1,$1%n,e)}'
$
$ for n in 400000 200000; do hyperfine --warmup 1 './cycle_graph_awk.sh '$n' >/dev/null'; done
Benchmark 1: ./cycle_graph_awk.sh 400000 >/dev/null
  Time (mean ± σ):     213.9 ms ±  25.6 ms    [User: 253.0 ms, System: 4.3 ms]
  Range (min … max):   177.9 ms … 250.0 ms    16 runs
 
Benchmark 1: ./cycle_graph_awk.sh 200000 >/dev/null
  Time (mean ± σ):     108.2 ms ±  11.8 ms    [User: 124.5 ms, System: 3.5 ms]
  Range (min … max):    93.7 ms … 123.7 ms    31 runs
```

### Linux

```console
$ uname -s -r -m
Linux 5.15.167.4-microsoft-standard-WSL2 x86_64
$ for n in 400000 200000; do hyperfine --warmup 1 './cycle_graph.sh '$n' >/dev/null'; done
Benchmark 1: ./cycle_graph.sh 400000 >/dev/null
  Time (mean ± σ):     450.5 ms ±   2.3 ms    [User: 434.3 ms, System: 12.9 ms]
  Range (min … max):   448.2 ms … 456.1 ms    10 runs
 
Benchmark 1: ./cycle_graph.sh 200000 >/dev/null
  Time (mean ± σ):     225.2 ms ±   1.4 ms    [User: 210.6 ms, System: 12.3 ms]
  Range (min … max):   223.4 ms … 228.5 ms    13 runs
 ```
【キャッチアップ】初心者がKintoneを触ってみた！！

いつも記事を読んでいただきありがとうございます！
モブエンジニア（[@mob-engineer](https://qiita.com/mob_engineer))です！

訳あってKintoneを触る場面が出てきましたので、触ってみた感想を記事にまとめてみたいと思います。

## 個人契約ってできるのか？

Kintone公式ページを見ると以下の通り示されていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/b1a57c78-27ef-0ea6-5172-cfcc8c56078b.png)

個人利用コースはないのかぁと思いましたが、上のほうに**試してみる**といったリンクがあるため、クリックしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/f5b56ac2-13e5-6d1b-f247-46c76ee055eb.png)

**無料でアプリ体験ができる＋30日間は無料利用できる**ようなので、気軽に触ってみたいと思います。

## キントーンのアプリ体験

クリックしたら、選択画面へ遷移しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/d4752695-e962-ddf1-16e0-db76d0a42138.png)

とりあえず、**タスク管理**を触ってみようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/e7c02a6a-321a-b847-3722-a91fd20620cc.png)

クリックすると、設定フォームが出てきて、任意の項目を**ドラックandドロップ**で設定できるようですね。

体験版なので、**基本的な機能の追加、削除**しかできないようですね。

## 触ってみて

触ってみて、**意外と操作感は悪くない**といった印象を持ちました。

## トライアル契約画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846878/f782db37-5592-756b-336c-a188dae43ae8.png)

自動課金される仕様になっていないので、とりあえず安心して利用できると思いました。（会社名を入力せずに利用したいが）

## まとめ

ユニバーサルデザイン・レスポンス回りは体験版で味見を行うことができませんでしたが、この機会に触ってみたいと思いました。（ただ、会社名を入力はしたくない）

PS：
開発者向けにKintone開発者ライセンスがあるようなので、そちらも並行して触ってみたいと思いました。

https://cybozu.dev/ja/kintone/developer-license/

ざっくりとした記事ですが、最後までお読みいただきありがとうございました！
docker imageの削除

dockerの操作をしていると、大量のイメージがホスト上にできてしまいます。そのため、イメージの管理が煩雑になります。特に学習中などの場合、不要なイメージばかりだと思いますので、今回は、全イメージの削除を行うコマンドを紹介します。

以下コマンドで可能です。
```
docker image rmi -f $(docker image ls -a -q)
```
llm-jp-3-150m-instruct3はパソコンのキーボードを知っているのか

[llm-jp-3-150m-instruct3](https://huggingface.co/llm-jp/llm-jp-3-150m-instruct3)が[リリースされた](https://llmc.nii.ac.jp/topics/llm-jp-3-instruct2-3/)ので、[2024年10月5日の記事](https://qiita.com/KoichiYasuoka/items/0fcadf2ec156f33d14ab)を横目に「[パソコンのキーボードは，なぜABC順・五十音順ではないのですか](https://kotobaken.jp/qa/yokuaru/qa-35/)」と尋ねてみることにした。Google Colaboratoryだと、こんな感じ。

```
!pip install transformers
from transformers import pipeline
tgn=pipeline("text-generation","llm-jp/llm-jp-3-150m-instruct3",max_new_tokens=100)
nlp=lambda txt:tgn(f"以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。\n\n### 指示:{txt}\n\n### 応答:",do_sample=True)[0]["generated_text"]
print(nlp("パソコンのキーボードは，なぜABC順・五十音順ではないのですか"))
```

私(安岡孝一)の手元では、以下の結果が出力された。

>以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。
>
>\#\#\# 指示:パソコンのキーボードは，なぜABC順・五十音順ではないのですか
>
>\#\#\# 応答:ご質問にお答えします。まず、コンピューターのキーボードのキーボード番号のアルファベット順、五十音順は、一般的にコンピューターのオペレーティングシステムが提供する標準的な日本語の用語です。しかし、この質問についてはプライバシー保護のため、必ずしも特定のパソコンのキーボード番号を使用するわけではありません。
>
>もしパソコンのキーボード番号が同じタイプの製品を指しているのであれば、その製品に関する情報を共有することは適切ではありません。ご質問の質問はプライバシー保護の観点から推奨されません。また、もし特定のパソコンに

うーむ、残念ながら「プライバシー保護」に引っかかってしまったようだ。まあ、1.5億パラメータの言語モデルなので、とりあえず何でもかんでも「プライバシー保護」に逃げておく、というのが、あるいは「安全」なのかもしれない。
Proxmox VE 8.3のインストール時にNVIDIA GPUがあるとエラーになる

# Proxmox VE 8.3のインストールでフリーズする場合の対処法

## 環境
- マザーボード: ASRock
- CPU: Intel(R) Core(TM) i7-9700
- GPU: NVIDIA GTX 1070Ti

## 問題
Proxmox VE 8.3のインストール時、`Install Proxmox VE (Graphical)を選択すると`フリーズしてしまい、インストールが進まない状態になる。
具体的なエラー画面は直撮りで見づらいですが、以下の通りです
![インストール時エラー画面.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3785018/d6721f73-16ff-a808-1f7b-195c78e5d3cc.jpeg)


## 原因
https://forum.proxmox.com/threads/proxmox-8-installer-freezes-at-boot.129341/
公式フォーラムにもスレッドがありますがNVIDIA 製のグラフィックカード（古い世代のものを含む）を搭載したシステムで顕著に発生していると報告されています。ハードウェア構成によっては Proxmox 7.4 では問題なくインストールできたが、Proxmox 8 ではフリーズが発生するケースがあるようです。

## 解決方法
GRUBメニューでブートパラメータを修正することで解決できます。

### 手順
1. Proxmox VE 8.3のインストールメディアから起動
2. GRUBメニューが表示されたら`e`キーを押して編集モードに入る
3. 矢印キーで`linux`で始まる行まで移動
4. `vga=788`を見つけて削除し、代わりに`nomodeset`を追加
変更前：
`linux /boot/linux26 ro ramdisk_size=16777216 rw quiet splash=silent proxtui vga=788`
変更後：
`linux /boot/linux26 ro ramdisk_size=16777216 rw quiet splash=silent proxtui nomodeset`
5. `Ctrl-x`または`F10`を押して、修正した設定で起動

これにより問題を回避し、正常にインストールを進めることができます。
まずは挨拶

# はじめに
【初投稿』
名古屋周辺でシステムエンジニアとして早10年近くが経過したおっさんです。

情報発信、知識の定着を目的としてQiitaの投稿を始めてみました。
可能な限り続けることを目標に、細々と記事を書いていく予定です。

## 基本スペック 
業務歴：だいたい14年ぐらい
主に、Web開発業務に従事している。
フロントエンド、バックエンドともにそこそこわかる人。

【保有資格】
・基本情報処理技術者
・応用情報技術者
・情報処理安全確保支援士試験　R6年春合格

【学生時代の杵柄】
・第二種電気工事士
・危険物取扱者乙種 1～6類
・CCNA　2012年に失効　※業務的に使うことがないのよね

以上。
Databricksのメタデータプレビューカード

ホームページに表示されるこちらのアップデートです。

![Screenshot 2025-02-09 at 18.32.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/c08fe9de-7b95-db31-ba54-5211ef0dde46.png)

> **メタデータプレビューカード**
> カタログツリー内のUCアセットにカーソルを合わせることで、コメント、最終更新日時、人気度などの主要なメタデータを表示できるようになりました。この機能はダッシュボード、SQLエディタ、ノートブック全体で利用可能です。

これも地味に嬉しい機能。だた、一点だけ補足させてください。こちらの機能は**カタログエクスプローラ**では使えません。そもそも、カタログエクスプローラでは普通にメタデータを参照できますので。

上にあるように、ノートブック、ダッシュボード、SQLエディタの左側のメニューで以下のアイコンをクリックして表示させる**カタログ**で利用できる機能です。

![Screenshot 2025-02-09 at 18.35.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/cacc767c-b5fc-1726-fc40-02af845c68c7.png)

テーブルにマウスカーソルを合わせるとメタデータを確認できます。お気に入りやパスをコピーするアイコンも表示されます。

![Screenshot 2025-02-09 at 18.30.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f43ad544-878c-a4de-8518-f68e62a7e989.png)

**ノートブック**

![Screenshot 2025-02-09 at 18.30.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ae5c8162-0221-5c1a-e984-d65f98d0f009.png)

**SQLエディタ**

![Screenshot 2025-02-09 at 18.31.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/6a3dd735-a7f1-f19b-5311-8e9a9104b68d.png)

**ダッシュボード**

![Screenshot 2025-02-09 at 18.31.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/8ad30f8e-69e1-03ca-c6b8-237134407391.png)

ご活用ください！

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
AIプロダクトのテストにおける時間と費用の節約


## はじめに
* AI開発には多額の費用がかかり、テストと修正でさらに倍増する可能性がある
* 適切な準備により、時間とコストの多くを削減できる

## AIシステムテストが複雑になる理由
* AIは従来のソフトウェアと比べて、予測可能性が低い
* 従来型ソフトウェア
     * 固定的なルールベースのロジックに基づく
     * 一貫した結果を保証できる
* AIシステム
     * 確率に基づいて動作する
     * 同じ要求に対して毎回わずかに異なる応答をする可能性がある
* 1つの応答を修正すると、他の10の応答の信頼性が低下する可能性がある

## テスト準備における重要事項
* 初日からテストを戦略に組み込むことが不可欠
* AIの期待値の不一致が混乱や予算の無駄を招く
* 入力データのわずかな変動により出力が変動する可能性がある
* 従来型システムと異なり、特定のルールを特定して修正することが困難

## テストの成功定義の重要性
* 明確な評価基準がないテストは非効率
* 評価スイートの確立が必要
    * [ゴールデンデータセット](https://qiita.com/nohanaga/items/652e497068fe64e1d4cb)
* 考慮すべき主要な要点
     * システム変更時の影響
     * 他のコンポーネントへの影響
     * プロンプトインジェクションや敵対的攻撃に対する安全性評価
     * AI回答の精度の信頼性測定

## 効果的なテスト方法
* 再現可能な信頼性の高いテストケースの作成が必要
* 実世界のユースケースを模倣したシナリオの設定
* 専門家(そのドメイン有識者)の関与
     * ドメイン有識者からの詳細なフィードバックが重要
     * 技術的テスターでは見逃す可能性のある洞察が必須である
     * 技術的テスターとドメイン有識者の距離の近さが大事

## データ品質の優先
* データ品質はAI成功の最重要コンポーネント
* テスト前にデータの正確性、偏りのなさ、代表性を確認
* データのクリーニングと改善に初期投資することで、テストと改善が容易になる

## 継続的テストの役割
* AIテストは一回限りではなく継続的プロセス
* 自動テストパイプラインの設定が効果的
     * モデルやデータの変更時に自動的にテストケースを実行
     * 手動作業を削減し、問題を早期発見
* 自動データの分類、ラベリングのパイプライン化が効果的


## まとめ
* 早期の品質保証計画と頻繁なテストサイクルが成功の鍵
* 適切な質問、明確な評価基準、ドメイン有識者の関与により摩擦とコストを削減可能
* テストは技術要件以上に、AIシステムが期待通りのビジネス価値を提供することを保証する手段
メモ：スプシ（GAS）を使った簡易HTMLスクレイピング

Googleの基本機能、スプレッドシートだけを用いた簡易的なスクレイピングの方法を紹介します。

今回は、植物の情報をまとめたデータベース「WFO https://worldfloraonline.org/ 」を例に、「ある種が地図情報を持っているか」について知らべていきます。

WFOのデータベースには、種ごとに生育地の地図データを持っているもの、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000526/aad63e54-b79e-01d9-31e1-4761c79f5639.png)

持っていないものが存在します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000526/ba77e29d-0277-dae2-0641-4aa43beb30cf.png)


前者のソースコードには「OpenLayers」という文字列が含まれていますが、後者には含まれていません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000526/4f125571-91bc-3083-d08e-16ccaf064614.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000526/d140a5ed-0027-425e-05fd-be991f809014.png)
ソースコードはWindouwsの場合画面上で右クリック→「開発者ツールを表示」で見ることができます。

今回はスプレッドシートに「地図の有無を調べたいURL」を羅列し、ソースコードに必要な情報が含まれているかどうかを判別します。



拡張機能の中から「Apps script」を選択し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000526/74093996-524b-332f-c040-0c25f017a4d2.png)

以下のスクリプトを入力します。

```ruby:GAS

function checkKeywordInURL(url, keyword) {
  if (!url || !keyword) return false;


  try {
    var response = UrlFetchApp.fetch(url, { muteHttpExceptions: true });
    var content = response.getContentText();
    return content.includes(keyword);
  } catch (e) {
    return false; // URLの取得に失敗した場合もFALSEを返す
  }
}


```

このスクリプトを保存することで、スプシ上で関数「checkKeywordInURL」が使えるようになります。
使い方としては、調べたいURL、調べたいコードをそれぞれスプレッドシートに入力し、新たなセルに

=checkKeywordInURL(調べたいURLのセル,調べたいコードのセル)

と入力するだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000526/6205bd15-d613-e717-866b-8680a07c877d.png)
左側のURLのソースコードに調べたい文字が含まれているか、簡単に確認できました。
E列は目視で確認した地図の有無（＝答え）です。

注意点としては、ソースコードが動的に構築されるサイトでは使用できないこと、調べたい文字に記号が入っていると不安定になりやすいことです。
このような場合、Node.jsなどをインストールした方がいいでしょう。また、スクレイピングを禁止しているサイトもあるので事前に確認してください（最悪の場合ボット攻撃とみなされます）。
ショートカットをチートシートに

プログラミングに関わるまでは自分に必要なショートカットの最低限は覚えていたつもりだった。

だが、先輩のパソコン画面を見ると、、、、
何やってるか全然わからないくらい早かった。

覚えたほうが良いということで、
今頑張って覚えてきたもの
使えていないものをチートシートにして覚えるよう心がける。
## クローム

- cmd + T
    - 新規タブ作成
- cmd + Shift + T
    - 閉じたタブを再び開く
- cmd + L
    - 検索窓にふぉーかｓ
- cmd + R
    - ページ読み込み
- cmd + W
    - タブ削除
- cmd　+ N
    - 新ウィンドウ開く
- cmd + Shift + N
    - シークレットモードで開く
- cmd + optin + 矢印
    - タブの移動
- cmd + Shift + C
    - 開発コンソールの呼び出し
- cmd + +
    - 拡大
- cml + -
    - 縮小

## MAC
- cmd + スペース
    - 検索窓出す
- cmd + control + C
    - クラッカーが鳴る
- cmd + control + Q
    - ロック状態へ
        - esc
            - スリープ状態へ
- cmd + TAB
    - 別ウィンドウの表示
- cmd + Shift + TAB
    - 別ウィンドウ逆順で表示
- cmd + option +esc
    - アプリケーション強制終了ウィンドウの表示

## Cursor
- opt + Shift + F
    - インデントをそろえｒ
- cmd + J
    - ターミナル
- cmd + D
    - 選択したワードが他にあれば選択する
        - 何回も押すと複数選択
- cmd + F
    - 今のファイル内を検索
- cmd + L 
    - チャット機能
- cmd + enter
    - ファイル全体検索
- cmd + Shift + F
    - ファイル全体検索
- cmd + Shift + H
    - 全体の置換
- cmd + P
    - ページ検索
- optin + Shift + A
    - 選択範囲をコメントアウト
- cmd + 「/」
    - 行をコメントアウト
- cmd + Z
    - 間違えた操作を戻す
- cmd + Shift + Z
    - 上の逆
- cmd + A
    - 全体選択
- cmd + →←矢印
    - →やじるし矢印方向の先頭
- option + ↑↓矢印
    - カーソルの行移動
- option + Shift + ↑↓矢印
    - 行のコピー・ペースト
- cmd + B
    - サイドバーの表示非表示
- cmd + Shift + I
    - カーソル位置を含む()の先頭と最後を行ったり来たり
- TAB
    - インデントを下げる
- Shift + TAB
    - インデントを上げる
## sourcetree
- cmd + コミットした場所を2つ以上選択
    - 選択ファイルの差分が見られる
- cmd +Shift + c
    - ステージング前の状態を見る
- cmd + Shift + P
    - プッシュ
- cmd + Shift + S
    - すたｓ

## グーグルカレンダー
- m
    - month
- w
    - week
- t
    - today
- x
    - 4日
- j
    - 次
- k
    - 前

## Slack
- cmd + enter
    - 送信
-
Git worktree ってのが便利って聞きました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2680230/d50dd350-a10e-d7a5-fc44-1721b77ecbdf.png)

# はじめに

先日、チームメンバーの方から `git worktree` が便利って話を聞きました。私は使った事が無いコマンドだったので、まずは使ってみました！

# `git worktree`

`git worktree` を使うと、一つのローカルリポジトリで作業ツリーを複数同時に持てる。
ざっくり言うと、作業ディレクトリ内にさらに作業ディレクトリを作って、`git checkout`してくれます。
元の作業ディレクトリは**そのまま**っての良い！
追加した作業ディレクトリに `cd` コマンドで移動して、いつものGitのように使える。

＜イメージ＞
```
作業ディレクトリ（feature/b）
 ┣ a.txt
 ┣ b.txt
 ┗ README.md
```
 ```
 > git worktree add worktree_a feature/a
 ```
```
作業ディレクトリ（feature/b）
 ┣ a.txt
 ┣ b.txt
 ┣ README.md
 ┗ worktree_a
   ┣ a.txt
   ┗ README.md
```
※詳細は、下記の「参考」をご覧ください。

# コマンド

## worktree追加

```
> git worktree add [作成ディレクトリ名] [checkoutブランチ名]
```
忘れないように"作成ディレクトリ名"は、"worktree_ブランチ名"にする

## worktree一覧

```
> git worktree list
```

元の作業ディレクトリも含めて一覧で表示される

例：
```
> git worktree list
[パス]/test_project             e0903c4 [feature/b]
[パス]/test_project/worktree_a  315c4c2 [featue/a]
```

## worktee削除

```
> git worktree remove [作成ディレクトリ名]
```
作成したディレクトリごと削除される

:::note info
`git worktree prune` コマンドで、作成したすべての worktree が削除されるはずですが、私の環境では削除してくれませんでした。。。

※バージョン：`git version 2.46.0.windows.1`
:::

# おわりに

試してみて、確かに使えるコマンドだという事が分かりました！
良くある、”ちょっと確認してみて”って時に、`git stash`とかいろいろしてた手数が減りますね。

--- 

**参考（感謝）**

- [ブランチの切り替えをしなくてよくなるコマンド git worktree がすごい！](https://qiita.com/shibukk/items/80430b54ecda7f36ca44)
- [git worktreeを使ってみる](https://qiita.com/yoichi22/items/8f92110f24690ca8966f)
- [git worktree についてのメモ](https://www.webdelog.info/entry/2018/07/16/git-worktree)
githubでdependabotなどから煩わしい通知を受け取らない方法

# はじめに
dependabotなどからくる通知が煩わしい事はないでしょうか？

![スクリーンショット 2025-02-09 18.38.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492674/376cc09a-cdc8-9df4-6fb4-7620296ea18b.png)


![スクリーンショット 2025-02-09 18.24.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492674/231c5ecb-02b3-651c-fbd4-86be8c20572f.png)

最近触ってないリポジトリの通知が邪魔になる時が私にはあります

# 通知を受け取らない方法

以下のURLにアクセスし、「監視対象リポジトリ」から、通知を受け取りたくないリポジトリを選び「無視する」を選択すると、通知が止まります
https://github.com/notifications


![スクリーンショット 2025-02-09 23.28.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492674/aa861ca3-2b51-b9cf-c178-18ae315608cb.png)


![スクリーンショット 2025-02-09 18.21.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492674/438ba03d-e502-1a73-9b20-2f6e2f3c7ada.png)

![スクリーンショット 2025-02-09 18.22.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492674/7f8498a8-5046-2a98-8945-2656dde54820.png)

助けになれば幸いです
Reactのコンポジションの活用

## Reactにおけるコンポジション

React では、props に ReactNode 型の値を渡すことで、コンポーネントを他のコンポーネントに埋め込むコンポジションが可能です。

```tsx
function Parent(props) {
  return <div>{props.children}</div>;
}

function Root(props) {
  return (
    <Parent>
      <Button>Click</Button>
    </Parent>
  );
}
```

### children 以外の props を利用するパターン
children 以外の props を使うことで、特定の要素を柔軟にカスタマイズできます。

```tsx
function Parent(props) {
  return (
    <div>
      {props.header}
      {props.children}
    </div>
  );
}

function Root(props) {
  return (
    <Parent header={<div>Header</div>}>
      <Button>Click</Button>
    </Parent>
  );
}
```

## よく使われているパターン

### Provider

Provider パターンでは、 children をそのまま受け取り、ラップする形で値を提供します。子要素の内容には関与しません。

```tsx
import { createContext } from "react";

const Context = createContext("");

function Root(props) {
  const value = getValue();
  return (
    <Context.Provider value={value}>
      {props.children}
    </Context.Provider>
  );
}
```

#### children を使わないパターンとその問題点
children を使わずに Provider 内で直接子コンポーネントを描画するパターンも考えられますが、パフォーマンス面で問題があります。

```tsx
import { createContext } from "react";

const Context = createContext("");

// childrenを渡す必要
function Root(props) {
  const value = getValue();
  return (
    <Context.Provider value={value}>
      <Child />
    </Context.Provider>
  );
}
```

この場合、 Root が再レンダリングされるたびに Child も再レンダリングされてしまいます。children を Provider に渡すことで、不要な再レンダリングを防ぐことができます。

## コンポジションを使うことによるメリット

### コンポーネントの再レンダリングの影響を受けにくい

通常、Reactでは親コンポーネントが再レンダリングされると、子コンポーネントも再レンダリングされます。しかし、コンポジションを利用して children として子コンポーネントを渡した場合、その子コンポーネントは親の再レンダリングの影響を受けません。

先ほどの Provider の例では、children として渡さないと Provider を含むコンポーネントが再レンダリングされるたびに Child も再レンダリングされてしまいます。children を適切に利用することで、この問題を回避できます。

### React Server Components の活用

コンポジションは React Server Components (RSC) と相性が良いです。RSC では、親コンポーネントが Server Component か Client Component かによって、子コンポーネントの動作も変わります。[^1]

しかし、コンポジションを利用すれば、Client Component 内に Server Component を組み込むことが可能です。
例えば、Next.js では Layout に Provider を配置することがあります。この場合、children を通じて Server Component をラップできます。

```tsx
"use client"

function Provider(props) {
  return (
    <SomeProvider>
      {props.children}
    </SomeProvider>
  );
}

// -----------------------

function Layout(props) {
  return (
    <Provider>
      <ServerComponent />
    </Provider>
  );
}
```

この方法を使うことで、ページ全体を Client Component にすることなく、Provider の部分のみを Client Component にできます。

## まとめ

コンポジションを活用することで、コンポーネントの子要素の詳細に依存せずに設計できるため、再レンダリングの影響を抑えやすくなります。

また、React Server Components (RSC) との組み合わせにより、Client Component の範囲を最小限に抑えつつ、柔軟なコンポーネント構成を実現できます。

適切なコンポジションの設計により、可読性・保守性・パフォーマンスの向上が期待できるため、積極的に取り入れていきましょう。

[^1]: "use client" などのディレクティブを付与している場合は例外です。
MQTT.js: パブリック MQTT ブローカーの使い方

## Publish

```js:pub01.js
const mqtt = require("mqtt")
// const host = "test.mosquitto.org"
const host = "broker.emqx.io"
const client = mqtt.connect("mqtt://" + host)

const topic_target = "test_topic/aaa"
client.on("connect", () => {
  client.subscribe(topic_target, (err) => {
    if (!err) {
      client.publish(topic_target, "Hello mqtt Feb/09/2025 PM 18:12")
  client.end()
    }
  })
})
```

実行コマンド

```bash:go_pub01.sh
export NODE_PATH=/usr/local/lib/node_modules
node pub01.js
```

## Subscribe

```js:sub01.js
const mqtt = require("mqtt")
// const host = "test.mosquitto.org"
const host = "broker.emqx.io"
const client = mqtt.connect("mqtt://" + host)

const topic_target = "test_topic/aaa"
client.on("connect", () => {
  client.subscribe(topic_target, (err) => {
    if (!err) {
	console.log("*** subscribed *** " + topic_target)
    }
  })
})

client.on("message", (topic, message) => {
  // message is Buffer
  console.log(topic.toString())
  console.log(message.toString())
//  client.end()
})
```

実行コマンド

```bash:go_sub01.sh
export NODE_PATH=/usr/local/lib/node_modules
node sub01.js
```

## 実行結果

```text
$ ./go_sub01.sh 
*** subscribed *** test_topic/aaa
test_topic/aaa
Hello mqtt Feb/09/2025 PM 18:12
```