OmniAICreator/Qiita-1.07M huggingface dataset:
CloudFrontディストリビューション削除時のWAFの挙動

2024/10/15

## CloudFrontディストリビューション削除時、WAFが削除されたかマネコン上で確認できなかったので、調べてみた。

![CloudFront WAF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3761697/f9f5673e-e286-4d11-929d-88f085db884c.png)




## CloudFront作成時に同時にWAFも作成

- 作成検証を終了
- リソースを削除時のマネコンでの挙動
- CloudFrontが削除されたことは画面から確認できたが、WAFの削除表示が無い？

## CloudFrontを削除すると、WAFも削除された

- 検証の結果、WAFも一緒に削除された。

## 確認操作
- WAF & Shield の画面から Web ACLs を選択　ー[Global (CloudFront)] 選択
- CloudFront 用の WAF の有無を確認できる。

![WAF&Shiled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3761697/c31d6b53-aa66-498e-afa2-648f67ddc5ec.png)
初めてのLT

## 先日 JAWS-UG 沖縄で初LTをしました！！

ついに！ずっと参加者として聴く側だった JAWS-UG 沖縄で、初めて LTデビューを果たしました！

正直、発表が決まってから当日まで緊張で何度も資料を見直しましたが、AWSコミュニティの温かい雰囲気に助けられ、無事に発表を終えることができました。  


---

### 発表内容

今回発表したテーマは  
**「私が10ヶ月でAWS全冠をとったお話し」** です。

IT未経験から資格をとり始め：

- なぜ全冠目指したか
- 私の学習法
- 学習の成果
- まとめ

これらを共有しました。

---

### 発表を終えて

5分という短い時間でしたが、以下の点を意識しました：

- 自分の言葉で話す（スライド読みながら話すと棒読みになった為）
- とにかく楽しむ
---

### JAWS-UG沖縄の魅力

改めて感じた JAWS-UG 沖縄の良さ：

- **初心者ウェルカムな雰囲気**  
  「初LTです」と言うと皆さん温かく応援してくれました
- **懇親会の盛り上がり**  
  技術談義はもちろん、沖縄ならではのビーチパーティ！！

---

### まとめ

初LTは想像以上に楽しく、学びの多い経験でした。  
アウトプットすることで自分の理解も深まりそしてもっとLTしたいと思えました！

そして今回のきっかけで  
**jaws-ug沖縄運営に入りました！！**  

まだLTをしたことがない方も、ぜひ一歩踏み出してみてください。  
JAWS-UGは初心者にも優しいコミュニティです！

[LT記事はこちら](https://speakerdeck.com/kana1166/awsren-ding-12guan-quan-zi-ge-qu-de-nohuo-yong)


## I Gave My First Lightning Talk at JAWS-UG Okinawa!

I made my LT (Lightning Talk) debut!

To be honest, I was nervous from the moment my talk was accepted until the day of the event. I kept revising my slides over and over. But thanks to the warm and supportive atmosphere of the AWS community, I was able to complete my talk successfully.

### Talk Overview
The theme of my talk was:
**"How I Earned All AWS Certifications in 10 Months"**

Starting from a non-IT background, I shared:

- Why I aimed for all certifications

- My study methods

- The results of my learning

- A quick summary

### Reflections on the Talk
Although it was just a 5-minute talk, I focused on:

- Speaking in my own words (Reading from the slides made me sound robotic)

- Enjoying the experience as much as possible

### The Charm of JAWS-UG Okinawa
What I re-discovered about JAWS-UG Okinawa:

Beginner-friendly atmosphere
When I mentioned it was my first LT, everyone encouraged me warmly.

Lively social gathering
We had fun chatting about tech, and of course—a beach party, Okinawa style!

### Summary
My first LT turned out to be more fun and insightful than I imagined.
By sharing my experiences, I deepened my own understanding and now I'm even more motivated to give future talks!

And most exciting of all:
I’ve joined the JAWS-UG Okinawa organizing team!

If you've never given an LT before, I encourage you to take the leap.
ONES Wikiのテーブル（表）機能を使いこなそう！

みなさん、今までExcelやGoogleスプレッドシートで表を作って管理していた項目、ありませんか？
実は[ONES Wiki](https://systemcon.co.jp/products/oneswiki/)にも便利なテーブル機能があります。今回は、この表機能の使い方と、便利な活用方法をご紹介します！

## 表を作ってみよう！
ONES Wikiのページ内で簡単に表を作れます。使い方はこんな感じです。
1. 編集モードで、表を作りたいところにカーソルを置く
2. トップバーの「挿入」→「テーブル」を選択
3. 表のサイズ（行数・列数）をマウスで指定すれば完成！

サイズを指定しないと、自動で「3行×5列」の表が挿入されます。後から自由に編集できるので安心してくださいね。

![テーブル設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3483972/5e07622f-11c8-40f6-9e4a-cc01c259a6c2.png)

## 表にいろいろな効果を追加してみよう
作った表に、さらに見やすくするための工夫を追加できます。

![効果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3483972/0247910c-3cf9-42d8-bec5-12475de0f4ce.png)

主な効果はこんな感じです、是非いろいろ試してみてください！
| 項目 | 効果 |
|:-:|:-:|
| セルの背景色  |  セルの背景色を変更できる |
| セルを結合  | セルを結合できる  |
| セルの結合を解除  | 結合されてたセルを元にもどせる  |
| 選択した行を削除  | 行を丸ごと消せる  |
| 選択した列を削除  | 列を丸ごと消せる  |
| 行見出し  | 行見出しを付ける  |
| 列見出し  | 列見出しを付ける  |
| 縞模様  | 行を１行飛ばしで縞模様にし見やすくできる  |
| 枠線を非表示  | 表の枠線を表示しない  |
| グラフを表示  | 表の内容をグラフにできる  |

## 行や列をカンタンに追加・削除する方法
表の行や列を追加する方法もカンタンです。
* 行を追加：表の左側の境界線にマウスを合わせると「＋」アイコンが出ます。クリックするだけで新しい行を追加！
* 列を追加：表の上側の境界線にマウスを合わせると「＋」アイコンが出ます。こちらもクリックひとつで追加できます。

![行、列の追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3483972/f373967e-1e21-4d10-81ca-97d6281ebae2.png)

削除する場合は、表の上または左の太線をクリックすると表示されるメニューから、行や列を簡単に削除できます。
また、表内の文字の装飾（太字、斜体など）もメニューバーから自由自在ですよ。

![削除.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3483972/d7f72c8d-faa2-4134-9d9e-86af9fd8d1ae.png)

## まとめ
ONES Wikiのテーブル機能を使うと、コンテンツを整理することができ、分かりやすくまとめることができます。

利用シーンは多く、とても効果的な機能で、相手に分かりやすく伝えやすいドキュメントを作成することができます。

ぜひONES Wikiのテーブル機能で便利な表を作って、分かりやすいドキュメントを作成してみてくださいね！
🚀 k0smotronをローカルでビルド&デプロイする最速ガイド

## ⚡ 30秒でk0smotronをkindにデプロイ

```bash
# リポジトリをクローン
git clone https://github.com/k0smotron/k0smotron.git
cd k0smotron

# Docker networkとkindクラスタを作成し、Cluster APIをInstallし、k0smotronをbuildしてkindへdeploy
make kind-capi-k0smotron
```

**これだけ！** 🎉

### 🔥 kindの設定を少し説明

```yaml
# config/samples/capi/docker/kind.yaml の中身
extraMounts:
  - hostPath: /var/run/docker.sock
    containerPath: /var/run/docker.sock
extraPortMappings:
  - containerPort: 31443
    hostPort: 31443
```

- **Docker socket マウント**: Cluster APIがDockerコンテナを管理するため必須
- **ポート31443公開**: k0smotronクラスタへの外部アクセス用
- **専用ネットワーク**: IP masqueradeでコンテナ間通信

## 💡 Pro Tips

```bash
# マルチアーキテクチャビルド（ARM64も対応！）
make docker-buildx PLATFORMS=linux/arm64,linux/amd64
```

## まとめ

k0smotronは**Kustomize**で構成管理され、**専用のkind設定**でCluster API対応の環境を簡単に構築できます。`make kind-cluster && make kind-deploy-k0smotron`で、ローカル開発環境が整うのは最高にクールです！

さあ、今すぐ試してみましょう！ 🚀
FireWall Manager セキュリティベースライン

2024/10/30

## FireWall Manager を触っていてわからない事項があったので、まとめてみました


**FireWall Manager セキュリティベースラインを整えるとは**

AWS Firewall Manager ではポリシーを定義することにより、組織内のアカウントに対して適用したいファイアウォールルールを一元的に設定及び管理することが可能。
具体的には、以下の 9 種類のポリシーを定義することが可能。



![Firewall Manager.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3761697/e38c2fcd-eaf2-4447-aa0c-dcb803ff11e1.png)



**< AWS サービス >**
- AWS WAF ポリシー
- AWS WAF Classic ポリシー
- AWS Shield Advanced ポリシー
- Security group ポリシー
- AWS Network Firewall ポリシー
- Amazon Route 53 Resolver DNS Firewall ポリシー
- Network ACL ポリシー

**< サードパーティサービス>**
- Palo Alto Networks Cloud NGFW ポリシー
- Fortigate Cloud Native Firewall as a Service ポリシー


[1] AWS Firewall Manager ポリシーの使用
https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/working-with-policies.html 


**AWS Firewall Manager を用いてセキュリティのベースラインを整える方法としては、以下のような例が挙げられる**


- AWS WAF ポリシーにて、組織内の複数のアカウントの ALB に同様の WebACL のルールを適用する。


- Security group ポリシーにて、組織内の複数のアカウントの未使用または冗長なセキュリティグループを監査して排除する。


- AWS Shield Advanced ポリシーにて、組織内の複数のアカウントを AWS Shield Advanced にサブスクライブし、ALB に Shield Advanced 保護を適用する。


- AWS Network Firewall ポリシーにて、組織内の複数のアカウントの VPC 全体に同様のファイアウォールを作成する。


- Network ACL ポリシーにて、組織内の複数のアカウントのサブネットに同様の Network ACL のルールを適用する。
Aurora グローバルデータベースを一時停止してみた

2024/07/29実施

- Auroraグローバルデータベースを作成したあと操作してみた。

  リソースを作成した後、「Auroraグローバルデータベース」を一時停止してみた。
  ところが、マネコンでそのような操作ができない。
  分かりにくい操作になっているか？それとも設定ミスか？

![IMG_2855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3761697/f4a644cc-631d-496b-8c5f-66961126f17f.png)




- 以下のメッセージ表示
  「Stop-db-cluster is not supported for clusters with read replicas」

##  結果
- グローバルデータベースの Aurora DB クラスターを個別に停止または起動することはできない。詳細については、「Amazon Aurora DB クラスターの停止と開始」を参照。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html#aurora-global-database.limitations

・SAPの試験勉強でデータベースのリソースの作成、設定パラメータの確認、
　どのような操作ができるか試して見た。
 　特にAWSが推奨する「Aurora」については自身で挙動を検証することは重要である。
HULFT SquareのAPIマネジメント機能で10MB以上のデータを返すための方法

## はじめに
HULFT SquareのAPIマネジメント構築では、最大10MBのデータまでしかレスポンスデータとして返すことはできません。もしそれ以上のデータを返したい場合にはどうすればよいかの回避策を本記事では記載していきます。

## ３つの回避策
今回はHULFT Squareで在庫情報を、社外の得意先へAPI基盤として公開したいということを考えます。その際APIで返すべき在庫情報が多く、10MBを超えてしまうという場合の回避策を３つご紹介します。

### 回避策①API結果の件数を絞る
1つ目の回避策は、返却するAPI結果の件数を絞る方法です。例えば、返すべき情報が1件2KBの場合、最大件数を5,000件とし、13,000件のデータを出力する場合、下記のような構成で回避可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4068471/65dc355d-e1b1-48e5-8634-08f06487cf90.png)
今回は件数で区切りましたが、例えば商品の「分類」毎で絞ることで、10MB以内に収めることができるのであれば、そういった絞り方でも問題ございません。
元データに「項番」がある場合は、そのまま「項番」を使い、「[指定された値]件目」～「[指定された値]＋5000件目」のデータを返すようにします。もしデータに「項番」なければ、HULFT Square ではデータに「項番」を振るということも可能なため、事前にデータに「項番」を与えておきます。

<dl>
  <dt>メリット</dt>
  <dd>
・[最大件数]を超えうる相手先にのみ、件数の指定が必要、その他の得意先は、意識することなく非常にシンプルにお使いいただける

・HULFT Square APIマネジメントの権限管理のみ管理すればよい
</dd>
  <dt>デメリット</dt>
  <dd>[最大件数]を超える得意先には、数度に分けてコールしていただき、データを結合する必要がある
</dd>
</dl>

またこの方法の場合、サーバ側で先のコールの情報を残しておき、それに応じた戻り値を2度目以降のAPIコールに対して行うということも考えられます。しかしREST APIは原則として、同じコールには同じリターンを返すべきであり、サーバ側が状態を保持しておくことはすいしょうされませ

### 回避策②API結果を共用クラウドストレージ上にファイルで書き出して共有することで連携
次の回避策はAPIで問い合わせた情報をそのままAPIで返却するのではなく、クラウドストレージへ書き出す方法です。構成は下記の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4068471/feb40002-4024-4ff7-b756-93596517df39.png)
共有のクラウドストレージへ書き出すことでAPIデータ量の制限を回避することが可能です。相手方は共有クラウドストレージからファイルとして取得します。

<dl>
  <dt>メリット</dt>
  <dd>データサイズを気にする必要がない
</dd>
  <dt>デメリット</dt>
  <dd>・相手方には別途クラウドストレージから結果を取得する必要がある

  ・クラウドストレージのユーザ/権限管理が別途必要
</dd>
</dl>

### 回避策③API結果をHULFT Square上にファイルで書き出し、SFTP転送で連携
最後の回避策も同じく、APIで問い合わせた情報をそのままAPIで返却するのではなく、今度はHULFT Square上にファイルとして書き出す方法です。構成は下記の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4068471/9d6e6e65-2f8b-40be-b6fb-e1e92195492a.png)

こちらも一度HULFT Squareのストレージにファイルとして書き込むことで、APIのデータ制限を回避可能です。相手方はSFTPサービスを使い、結果を取得します。またHULFT Squareは自身の機能で、サービス上にSFTPサーバを建てることも可能です。

<dl>
  <dt>メリット</dt>
  <dd>データサイズを気にする必要がない
</dd>
  <dt>デメリット</dt>
  <dd>・相手方には別途SFTPで結果を取得する必要がある

  ・SFTPのユーザ管理が別途必要
</dd>
</dl>

# 最後に
いかがでしたでしょうか。今回はHULFT SquareのAPIマネジメント機能のデータサイズの制限への回避策について記載しました。10MBといった制限に直面した人を救うことができれば幸いです。また３つの回避策の内「①API結果の件数を絞る」はHULFT Squareだけで実現することが可能な回避策です。特に別の理由がなければ最も推奨できるほうほうだと考えています。
ここまで読んでいただきありがとうございました。
[HULFT Squareについて知りたい方はこちら](https://www.hulft.com/service/hulft-square)
SuiteQL (SQL) で NetSuite のログイン監査を簡単に


[前回の記事](https://qiita.com/fujitak/items/9622ea1d0aa9692f7ad6) では、SuiteQL（NetSuite 専用 SQL）の活用方法を、製造業のBOM（部品表）を例に、ご紹介いたしました。

今回は、NetSuite 2026.1 （2026年の春）のアップデートにて適用される「NetSuite2.com データソース」への完全移行に伴い、旧式の「NetSuite.com データソース」を使用しているユーザー特定するための、SuiteQLクエリの例をご紹介します。

データソース移行に関する NetSuite 管理者向けの詳細は、以下をご参照ください：
[NetSuite サポートコミュニティ› お知らせ › NetSuite2.com データソースへの移行が必要です](https://community.oracle.com/netsuite/japanese/discussion/4507919/)

※ 上記の内容は、対応が必要なお客様へ、メールやNetSuiteの画面上で、かねてよりNetSuite 管理様などへご連絡差し上げております。
<br>

**クエリの例**
以下の SuiteQL クエリは、過去180日間において「旧式データソース」を利用したユーザー情報を取得します。
```
SELECT
       cla."user"        AS user_id,
       emp."entityid"    AS user_name,
       emp."email"       AS user_email,
       MAX(cla."date")   AS last_netsuite_com_login,
       COUNT(*)          AS netsuite_com_login_count
FROM   "ConnectLoginAudit" cla
JOIN   "Employee"        emp ON emp."id" = cla."user"
WHERE  cla."dataSource" = 'NetSuite.com'  -- 旧式
  AND  cla."date"      >= CURRENT_DATE - 180
GROUP  BY cla."user", emp."entityid", emp."email"
ORDER  BY last_netsuite_com_login DESC;
```
<br>

**実行結果**
前回の記事でご紹介したサンプルアプリでのクエリの実行結果は以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3431564/16430082-8a3b-4b7b-b56a-5a98176fc593.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3431564/d1cb9730-4e28-4076-85cb-518402219aa0.png)

<br>

**SQL構文の補足**
今回のクエリでは以下のSQLの基本を利用しています。
- SELECT句: 取得する情報（列）を指定
- JOIN句: 異なるテーブル間の関連付け
- WHERE句: データ取得の条件を指定
- GROUP BY句: 特定の列を基準にデータを集約
- ORDER BY句: 結果の並び替え条件を指定
<br>

**まとめ**
このようにSuiteQLはSQLの標準的な構文を使いながら、NetSuite内のデータを簡単かつ柔軟、そして安全に取り扱うことができます。NetSuiteも含めた標準システム全体のデータ活用の一環として、SuiteQLをご活用頂けますと幸いです。
<br>

**参考リンク**
[Oracle NetSuite Help Center > SuiteQL](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_156257770590.html)
[Oracle NetSuite Help Center > N/llm Module](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_9123730083.html#subsect_1014032311)
[NetSuite サポートコミュニティ› AI関連機能› SuiteScript 2.x 生成AI API](https://community.oracle.com/netsuite/japanese/discussion/4503315/suitescript-2-x-%E7%94%9F%E6%88%90ai-api#latest)
[NetSuite サポートコミュニティ› お知らせ](https://community.oracle.com/netsuite/japanese/categories/%E3%81%8A%E7%9F%A5%E3%82%89%E3%81%9B)
<br>


© 2025 Takusuke Fujii
本記事は CC BY 4.0（原作者名の表記が必要）で自由に共有・改変・配布できますが、無保証につき著作者は一切責任を負いません。
Copilot Studioで「全般的な指示」とは異なる個別指示を使う方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/5dc57b09-e1ac-41bf-af78-f90a025e47bb.png)

Copilot Studioを使っていると、**全般的な指示**と**トピックごとの指示**の使い分けが必要なケースが出てきます。  
たとえば、全体では「Q&A対応をする」と指示しているが、あるトピックだけは「メール文案を作成したい」といった場合です。

## 目的

本記事では、**全般的な指示とは別の個別の指示を「生成型の回答を作成」で反映させる方法**を紹介します。

---

## 方法

トピック内で「生成型の回答を作成」する際、以下のように**ノード内の指示文**に記述を追加します。

### ノード指示文の書き方



全般的な指示はすべて無視する。
以下の指示に従って回答を作成せよ：
（ここに個別の指示を書く）



### 例：


全般的な指示はすべて無視する。
以下の指示に従って、件名・本文を含むメール文案を作成せよ。



## 検証結果

実際に以下のような構成でテストを行い、期待通りに動作することを確認しました。

- **全般的な指示：** Q&A対応を行う
- **トピック内のノード指示：** メール文案の作成を指示（全般的な指示を無視）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/11027b42-c93e-40d0-95af-b2b4631b2508.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/142f4847-e88c-4cbe-85b5-aa8fea4d5ad0.png)

結果として、該当のトピック内ではQ&A形式ではなく、意図した**メール文案**が生成されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/d734db7e-30df-4beb-9592-658ade63ecc9.png)

---

## まとめ

Copilot Studioでは、**トピック単位で全般的な指示を無効化し、独自の応答を作らせる**ことが可能です。

### ポイント
- 「全般的な指示はすべて無視する」と明記する
- 続けてトピックごとの具体的な指示を記述する

これにより、より柔軟にユースケースに応じた対話設計ができるようになります。
DagsterのAssetCheckでパーティション情報を取得する　～Dagster備忘録～

# 結論

結論だけサクッと書きます。

```python
def get_partition_key(context: dg.AssetCheckExecutionContext) -> str:
    step_context = context.get_step_execution_context()
    partition = step_context.partition_key
    return partition
```

AssetCheckに渡されるContextを上記の関数に渡せばOKです

<br>
以下、実際の`@asset`と`@asset_check`のコードも記述します。
(実践的には`@multi_asset_check`の方を使うことが多いらしいので、サンプルコードはそちらで書きました。どちらにしても挙動は変わらないはずです)

```python
# Asset
@dg.asset(
    compute_kind="duckdb",
    group_name="ingestion",
    partitions_def=vresion_partition,
    metadata={"table_name": "products"},
)
def products(context: dg.AssetExecutionContext, duckdb: DuckDBResource) -> str:
    context.add_output_metadata(
        {"dynamic_add": "123"}
    )
    context.add_asset_metadata(  
        metadata={
            "row_count": 567,
            "preview": "preview",
        }
    )
    return "products"

# 以下AssetCheckコード
@dg.multi_asset_check(
    specs=[
        dg.AssetCheckSpec(blocking=True, name="record_num_check", asset="products"),
        dg.AssetCheckSpec(blocking=True, name="value_check", asset="products"),
    ]
)
def check_products(context: dg.AssetCheckExecutionContext) -> Iterable[dg.AssetCheckResult]:
    # 現在のパーティションのメタデータ取得
    partition = get_partition_key(context)

    # チェックロジック（例としてダミー）
    is_ok = True

    yield dg.AssetCheckResult(
        check_name="record_num_check",
        passed=is_ok,
        asset_key="products",
        partition=partition
    )

    value_is_ok = True
    yield dg.AssetCheckResult(
        check_name="value_check",
        passed=value_is_ok,
        asset_key="products",
        partition=partition
    )

```

`@asset`と`@asset_check`ではcontextの型が違うので、そこは注意が必要です。

本当は親AssetのMetaデータまでは取得したかったのですが、深ぼっても見当たりませんでした。
やりようはある気がしますが、パーティションさえ取得できればデータチェックに必要なデータは揃うので、今回はここで撤退することにしました。
有識者の方がいらっしゃいましたら、是非ともご教授お願いいたします。
laravel ✕ OAuth2.0 Socialiteを使ったアクセストークン取得でリフレッシュトークンが取得できない

## 概要

下記の内容を実施してSocialite側からスコープを設定した。

https://qiita.com/miriwo/items/9faf77f111c53e58ab51

その後web.phpのログイン側の処理にてOAuth2.0のアクセストークンとリフレッシュトークンを取得する処理を記載した。

```routes/web.php
// Googleからのコールバックを受け取る
Route::get('/auth/callback', function () {
    try {
        $googleUser = Socialite::driver('google')->user();
        $accessToken = $googleUser->token;
        $refreshToken = $googleUser->refreshToken;
    } catch (Exception $e) {
        Log::error($e);
        return redirect(route('home'));
    }

    Log::info('accessToken: ' . $accessToken);
    Log::info('refreshToken: ' . $refreshToken);

    // ユーザーが既に存在するか確認
    $user = User::where('email', $googleUser->getEmail())->first();

    if (!$user) {
        // ユーザーが存在しない場合、新規作成
        $user = User::create([
            'name' => $googleUser->getName(),
            'email' => $googleUser->getEmail(),
            'google_id' => $googleUser->getId(),
            'password' => Hash::make(Str::random(16)),
        ]);
    }

    // ユーザーをログインさせる
    Auth::login($user);

    // リダイレクト先を指定
    return redirect(route('dashboard'));
})->name('google.callback');
```

修正した処理を画面側からの操作で実行し、ログを確認するとaccessTokenは出力されているが、refreshTokenが出力されていない。
この問題を解消する方法をまとめる。

## 解消方法

Googleの認証画面にリダイレクトする処理を下記のように修正する。

```routes/web.php
// Googleの認証ページへのリダイレクト
Route::get('/auth/redirect', function () {
    return Socialite::driver('google')
        ->scopes(['email', 'profile', 'https://www.googleapis.com/auth/cloud-platform.read-only'])
        ->with(['access_type' => 'offline', 'prompt' => 'consent']) // こちらを追記
        ->redirect();
})->name('google.redirect');
```

これでトークン取得リクエストのレスポンスでリフレッシュトークンが返るようになる。

## 問題の特定方法

1. `vendor/laravel/socialite/src/Two/AbstractProvider.php`の`user()`の中に`dd()`を記載してレスポンスを出力してみる

    ```vendor/laravel/socialite/src/Two/AbstractProvider.php
    /**
     * {@inheritdoc}
     */
    public function user()
    {
        if ($this->user) {
            return $this->user;
        }

        if ($this->hasInvalidState()) {
            throw new InvalidStateException;
        }

        $response = $this->getAccessTokenResponse($this->getCode());
        dd($response);

        $user = $this->getUserByToken(Arr::get($response, 'access_token'));

        return $this->userInstance($response, $user);
    }
    ```

1. laravel側のアプリケーションで一旦ログイン後に`/auth/redirect`にアクセスし、再度ログイン
1. レスポンスの中にrefreshTokenのキーバーリューが存在していない
1. 前述した`->with(['access_type' => 'offline', 'prompt' => 'consent'])`を追記
1. laravel側のアプリケーションで一旦ログイン後に`/auth/redirect`にアクセスし、再度ログイン
1. レスポンスの中にrefreshTokenのキーバーリューが存在するようになった
1. `vendor/laravel/socialite/src/Two/AbstractProvider.php`の`user()`の中の`dd()`を削除
1. laravel側のアプリケーションで一旦ログイン後に`/auth/redirect`にアクセスし、再度ログイン
1. ログにアクセストークンとリフレッシュトークンが出力された
WRFテストラン手順 その2（WPS編）

## 1. 概要

ここでは、[前回の記事](https://qiita.com/pokitamazaing/items/5000efc13ce411275d17)に引き続いて，WPSの各コンポーネント（`geogrid.exe`, `ungrib.exe`, `metgrid.exe`）の実行順序と必要なコマンドをまとめます．
せっかくなので既往の記事で紹介されているFNLデータではなく，気象庁GSM（全球）を用いたテストランを行ってみようと思います．

---

## 2. 前提

* WRF/WPSは `~/WRF/WPS-4.6.0/` にインストール済み．

* `namelist.wps` は例えば以下のように事前に編集済みとする（Streamlit GUI等を活用して1段階ネスティングで設定，[前回の記事](https://qiita.com/pokitamazaing/items/5000efc13ce411275d17) ）．

```namelist.wps
&share
 wrf_core = 'ARW',
 max_dom = 2,
 start_date = '2025-05-05_00:00:00','2025-05-05_00:00:00',
 end_date = '2025-05-08_00:00:00','2025-05-08_00:00:00',
 interval_seconds = 21600
/

&geogrid
 parent_id = 1,1,
 parent_grid_ratio = 1,4,
 i_parent_start = 1,110,
 j_parent_start = 1,160,
 e_we = 500,301,
 e_sn = 500,301,
 geog_data_res = 'default','default',
 dx = 5000,
 dy = 5000,
 map_proj = 'lambert',
 ref_lat = 37.0,
 ref_lon = 138.0,
 truelat1 = 37.0,
 truelat2 = 37.0,
 stand_lon = 138.0,
 geog_data_path = '/home/user/WRF/WPS_GEOG'
 OPT_GEOGRID_TBL_PATH = '/home/user/WRF/WPS-4.6.0/geogrid'
/

&ungrib
 out_format = 'WPS',
 prefix = 'GRIBFILE',
/

&metgrid
 fg_name = 'GRIBFILE'
 OPT_METGRID_TBL_PATH = '/home/user/WRF/WPS-4.6.0/metgrid'
/
```

* 実行用ディレクトリは以下とする．

```bash
~/WRF/WPS-4.6.0/RUN/run_project_20250603/
```

---

## 3. GRIBデータのリンク

取得済みのGSMデータ（またはFNLデータ）をWPS用にリンク．

```bash
cd ~/WRF/WPS-4.6.0/RUN/run_project_20250603
../../link_grib.csh ../../../GSM_DATA/
```

リンク成功後、`GRIBFILE.AAA`, `GRIBFILE.AAB`, ... のファイル群がrunproject内に生成されます．

---

## 4. 地形データのリンク

地形データをリンクする．以下のように`namelist.wps`に追記しておきます（各自のPATHに合わせる）．

```namelist.wps
OPT_GEOGRID_TBL_PATH = '/home/user/WRF/WPS-4.6.0/geogrid'
```

---

## 5. `geogrid.exe` の実行

```bash
./geogrid.exe
```
---

NETCDF形式でgeogridのファイル群が生成されます．

## 6. `ungrib.exe` の準備と実行

### a. Vtable のリンク

読み込ませる気象データに対応する `Vtable` を選択してリンク．

例（気象庁GSM の場合）：

```bash
ln -sf ../../ungrib/Variable_Tables/Vtable.GFS Vtable
```
（Vtable.JMAGSMというのも同じディレクトリにあることは確認したんですが，テストランはしてません）

### b. 実行

```bash
./ungrib.exe
```

grib2形式のデータが先ほどリンクした`Vtable`を用いてungribされます．

---

## 7. `metgrid.exe` の準備と実行

### a. METGRID.TBL のリンク

```namelist.wps
OPT_METGRID_TBL_PATH = '/home/user/WRF/WPS-4.6.0/metgrid'
```

metgridでungribされた気象データとgeogridによる地形データが統合され，`met_em.*.nc`が入力時系列の分だけ作成されます．

### b. 実行

```bash
./metgrid.exe
```

---

次は「[その3（WRF実行編）](https://qiita.com/pokitamazaing/items/de7eacb2e35e04febd4c)」で最終的なWRFの計算として，コンパイル済みの`./real.exe`，`./wrf.exe`の実行を行っていきます．

---
Diffを取る

業務でツールを使用せずテキストファイル出力でdiffを撮りたい機会があったので今後にためにメモ。

## 2ファイルのdiffを取り、結果をmdファイルで出力する(PowerShell)

・Aファイルを修正し、Bファイルとのdiffを取ることを想定。
まず、コマンドは以下。

```ruby:test.ps1
$sPath = Aファイルパス
$bPath = Bファイルパス
$outPath = 出力したいディレクトリパス（"C:¥work¥out¥diffResult.md"）
Compare-Object -ReferenceObject (Get-Content $aPath -Encoding UTF8) -DifferenceObject (Get-Content $bPath -Encoding UTF8) | Out-File $outPath -Encoding UTF8
```

・これで"C:¥work¥out¥diffResult.md"にAファイルとBファイルの差異が出力される

## 用語解説
上記のコードのコマンド詳細とPowerShellの基礎的なことを下記に記述する。

# 変数

**変数**
PowerShellでは、変数の宣言・代入が行える。

```ruby:構文
$変数名 = 代入する値
```
# パイプ（ | ）

左辺の処理の実行結果を右辺の処理の入力情報として渡すことができる。

```ruby:構文
左辺の処理 | 右辺の処理
```

# Compare-Object
2つのファイルを比較したいときに使うコマンド

```ruby:構文
Compare-Object -ReferenceObject (Get-Content "比較対象ファイル①") -DifferenceObject(Get-Content "比較対象ファイル②") | Out-File -FilePath '出力先ファイル' -Encoding utf8
```

# Out-File
PowerShellで実行したコマンドの出力結果をファイルに保存するためのコマンド。

```ruby:構文
<コマンド> | Out-File [-FilePath]<文字列>[-Encoding<文字列>][-Append]
```

**-FilePath**
出力先となるファイルパス。

**-Append**
既存のファイルの末尾に出力を追加したい場合。デフォルトでは既存ファイルを上書きする

**-NoClobber**
同名のファイルが存在する場合、上書きせずにエラーを出すようにする

## mdファイルとは？

ここで、上司から「mdファイルに出力してください」との指示があったので、「mdファイルってなんぞや？」と調べた内容をメモ。

**.mdファイル**
Markdoenというマークアップ言語で記述された文書のファイル。テキストデータなので、テキストファイルで開くことが一般的。HTMLの簡易版ですね。
Sandboxで.invalid のついたメールアドレスを変更する





[Sandbox user email change does not contain a way to accept the email change](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A91RvSAJ)

上記にもあるように.invalidを削除してから、パスワードをリセットしてユーザーに通知するをオンにすれば解決すると思っていたのですが... 


実際に届いたメールのリンクをクリックすると... ログイン画面なんですよね。

スクリーンショットを取り損ねました...


ここに回答がありました。

+ [User cannot access Sandbox - stuck in a loop](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KBlWr)


:::note
I found that I had to "Unfreeze" the accounts first.  Once the accounts were unfrozen, I was able to change the email address.  The users received the link to verify the email change and when they clicked the link they get a pop-up message that the email change was successful.  They still end up at the login screen, so it can be confusing.  However, the email address does get changed and then I can reset the password.

まずアカウントを「凍結解除」する必要があることがわかりました。アカ​​ウントの凍結解除後、メールアドレスを変更できました。ユーザーにはメールアドレスの変更を確認するためのリンクが送信され、リンクをクリックすると、メールアドレスの変更が成功したことを示すポップアップメッセージが表示されます。それでもログイン画面が表示されるため、少し混乱するかもしれません。しかし、メールアドレスは変更され、その後パスワードをリセットできます。
:::

確かに凍結されていますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/369f5932-b54d-4cfd-a0cf-74a42c175fb0.png)

解除ボタンをクリックした後に、私が認識している手順を試すとちゃんとパスワードリセットの画面になりました。
【蔭山公望の主観】SNSで「バズらない投稿」が売上につながる理由



こんにちは、蔭山公望です。

SNSマーケティングにおいて、多くの方が「バズる」ことを目指していますが、
実際には「バズらない投稿」が売上につながるケースも少なくありません。
今回は、その理由について考察してみたいと思います。

バズらない投稿の価値
バズる投稿は一時的な注目を集めることができますが、必ずしも購買行動につながるとは
限りません。一方で、地道に発信を続けることでフォロワーとの信頼関係を築き、
長期的な売上につなげることが可能です。

信頼構築の重要性
SNSは単なる情報発信の場ではなく、顧客とのコミュニケーションの場でもあります。
日々の投稿を通じてブランドの価値観やストーリーを伝えることで、フォロワーとの
信頼関係を深めることができます。

購買行動への影響
信頼関係が築かれると、フォロワーはブランドの商品や
サービスに対して興味を持ち、
購買行動につながる可能性が高まります。

また、フォロワー自身がブランドのファンとなり、口コミや紹介を通じて
新たな顧客を
獲得することも期待できます。

まとめ
SNSマーケティングにおいては、バズることだけが成功の指標ではありません。
地道な発信を続け、フォロワーとの信頼関係を築くことが、長期的な売上につながる鍵となります。

このように、バズらない投稿でも売上につながる理由を理解し、
戦略的にSNSを活用することが重要です。
laravel Socialite 権限委譲確認画面を再度表示する方法

## 概要

GoogleのOAuth2.0の権限委譲確認画面を再度表示する方法を簡単にまとめる。

## 前提

コードは下記の内容を実施した直後の状態

https://qiita.com/miriwo/items/9faf77f111c53e58ab51

## 内容

後述のように`->with(['prompt' => 'consent'])`を追記することで下記の画面を再度表示する事ができる。

- テスト状態であることの確認
- 権限委譲の確認


```web.php
// Googleの認証ページへのリダイレクト
Route::get('/auth/redirect', function () {
    return Socialite::driver('google')
        ->scopes(['email', 'profile', 'https://www.googleapis.com/auth/cloud-platform.read-only'])
        ->with(['prompt' => 'consent'])
        ->redirect();
})->name('google.redirect');
```
自作osファイルに関して

unix鉄画にも通ずるかな？一つのことをうまくやらせる、、、

コピー対象のファイルを「仮想メモリのメモリブロック」として扱い、メモリ書き込み命令でコピー
ファイルコピー＝メモリブロック操作 という名の黒魔術
ファイル操作がメモリ操作だけでできる->osサイズをちいさくできるやつ
Streamlit の使い方

Ubuntu 25.04 で Streamlit を使ってみました。
こちらを参考にしました。
[Install Streamlit using command line](https://docs.streamlit.io/get-started/installation/command-line)

## インストール

Pip を使うので Python の仮想環境を使いました。

```bash
source $HOME/myenv/bin/activate
```

```text
$ which python
/home/uchida/myenv/bin/python

$ python --version
Python 3.13.3
```

```bash
pip install streamlit
```

インストールされたことの確認

```text
$ which streamlit
/home/uchida/myenv/bin/streamlit

$ streamlit --version
Streamlit, version 1.45.1
```

## テストラン

```bash
streamlit hello
```

```text
$ streamlit hello

  Welcome to Streamlit. Check out our demo in your browser.

  Local URL: http://localhost:8501
  Network URL: http://192.168.1.8:8501

  Ready to create your own Python apps super quickly?
  Head over to https://docs.streamlit.io

  May you create awesome apps!
```

ブラウザーで、http://localhost:8501/　にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/4ad5cfc1-f838-4167-aa32-6978dede86b1.png)

## 簡単なプログラム

```py:app.py
import streamlit as st

st.write("Hello world")
st.write("Good Morning")
st.write("こんにちは")
```

実行

```bash
streamlit run app.py
```

```text
$ streamlit run app.py

  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://192.168.1.8:8501
```

ブラウザーで、http://localhost:8501/　にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f1cac17a-78fc-496b-97b4-80e2f9ec55e7.png)

## もう少し複雑なサンプル

```py:app.py
import streamlit as st

st.title('二乗')
st.text('こんにちは')
input_num = st.number_input('数字を入れて下さい', value=0)

result = input_num ** 2
st.write('結果: ', result)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/75f4adb1-141b-400a-a84c-1a3b149f5d81.png)

数字を入れると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/454f46fb-6cb7-4077-b306-1e77beb23967.png)
laravel ✕ OAuth2.0 Socialiteライブラリを使ってOAuth2.0のアクセストークンを取得するときに実行しているリクエストのパラメーターが定義されている場所

## 概要

laravelのSocialiteライブラリにてアクセストークンを取得するためのリクエスト送信時のパラメーターが定義されている場所を特定する。

## 定義場所

`vendor/laravel/socialite/src/Two/AbstractProvider.php`

```vendor/laravel/socialite/src/Two/AbstractProvider.php
    /**
     * Get the access token response for the given code.
     *
     * @param  string  $code
     * @return array
     */
    public function getAccessTokenResponse($code)
    {
        $response = $this->getHttpClient()->post($this->getTokenUrl(), [
            RequestOptions::HEADERS => $this->getTokenHeaders($code),
            RequestOptions::FORM_PARAMS => $this->getTokenFields($code),
        ]);

        return json_decode($response->getBody(), true);
    }

    /**
     * Get the headers for the access token request.
     *
     * @param  string  $code
     * @return array
     */
    protected function getTokenHeaders($code)
    {
        return ['Accept' => 'application/json'];
    }

    /**
     * Get the POST fields for the token request.
     *
     * @param  string  $code
     * @return array
     */
    protected function getTokenFields($code)
    {
        $fields = [
            'grant_type' => 'authorization_code',
            'client_id' => $this->clientId,
            'client_secret' => $this->clientSecret,
            'code' => $code,
            'redirect_uri' => $this->redirectUrl,
        ];

        if ($this->usesPKCE()) {
            $fields['code_verifier'] = $this->request->session()->pull('code_verifier');
        }

        return array_merge($fields, $this->parameters);
    }
```
【トラブル】Spring BootでMyBatisを使おうとしたらTimestampのカラムでエラーが出る

SpringBootのMyBatisで以下のようなエラーが発生しました

```
Caused by: java.lang.IllegalStateException: No typehandler found for property createdAt
```

こちらがそのDomainになります

```java
package com.example.demo.domain;

import java.security.Timestamp;

import lombok.Data;

@Data
public class Employee {
	int id;
	String name;
	String jobCategory;
	String jobCategoryName;
	Timestamp createdAt;
	Timestamp updatedAt;
}
```

こちらが正しいDomainです。

```java
package com.example.demo.domain;

import java.sql.Timestamp;

import lombok.Data;

@Data
public class Employee {
	int id;
	String name;
	String jobCategory;
	String jobCategoryName;
	Timestamp createdAt;
	Timestamp updatedAt;
}

```

`java.sql.Timestamp`でTimestampを定義していないと発生するようです。
ややこしいですね(;^ω^)
Laravelのレスポンスが [] になる時の対処法

今回はCRUD処理だけなので、各種Controllerを共通化するためモデルを ```as Model``` にしてコピペで量産するようにしていました。変数名もそれに合わせて ```$model``` としましたが取得結果が```[]``` しか返ってこなくなりました..

結果として、Controllerメソッドの変数名がメソッドインジェクションに対応する変数名（単数系キャメルケースのモデル名）になっていないと ```[]``` が返るようです。  

そんなもの実装に依存させるな..

#### showメソッドの例

```diff
<?php

namespace App\Http\Controllers;

use App\Models\User as Model; // <-- 共通化しようとした
use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Display the specified resource.
     */
-    public function show(Model $model)
+    public function show(Model $user)
    {
-        return $model; // -> []
+        return $user; // -> {id: 1, name: 'hogemoge', ...}
    }
}

```

Laravelは初学者の教科書としては良いですが、大きなお世話が過ぎます。
今回の異変に関しても、メソッドインジェクションはコード上から追えない「ミッシングリンク」になっている実装（良く言えば隠匿された実装）なので、StackOverflow に記事がなければ数日解決できない可能性が高かったです。
弊社も今の作業が終われば完全に Laravelフリー な環境になるのですが、最後の最後に一矢報われました…
プロキシ環境下でのGRPC C++開発環境構築

# プロキシ環境はいろいろと大変

会社の環境では、プロキシサーバが導入されているゆえにnpm, pip, nugetなど一般的なパッケージマネージャーが簡単には使えない。
今回はvcpkgを使いたかったがどうしても会社環境ではうまくいかなかったので遠回りした環境構築を記録する

# gRPC + CPP + Visual Studio

ほかのブログなどを見るとvcpkgを使ってgrpcのインストールをするのが一般的な模様。
しかし、先述の通りvcpkgがうまく使えなかったのでgRPCのソースコードを持ってきてビルドしてインストールする。
Cmakeを使うが、相変わらずこのツールは難しいし、理解したいとも思わない。

## .protoファイルからC++のコード生成

1. Visual Studioインストール
   - C++のビルド環境構築のため
2. CMakeのインストール
   - https://cmake.org/download/
3. gRPCのソースコードビルド
   1. Githubからソースコード取得
      - https://github.com/grpc/grpc
   2. ビルド結果をインストールするフォルダを決定
      - ex) C:\grpc
   3. 環境変数にインストールフォルダを設定
      - GRPC_INSTALL_DIR=C:\grpc
   4. 環境変数のPATHにバイナリへのパスを追加
      - C:\grpc\bin
        - proto.exe
        - grpc_cpp_plugin.exe
        - を使うため
   5. ビルド
        ```bash
        cd ./cmake/build
        cmake -A x64 -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF "-DCMAKE_INSTALL_PREFIX=$env:GRPC_INSTALL_DIR" -DCMAKE_BUILD_TYPE=Release ../..
        cmake --build . --target install
        ```
   6. C:\grpcにフォルダができていれば成功
4. protoファイルのコンパイル
    ```bash
    protoc -cpp_out=./ --grpc_out=./ "plugin=protoc-gen-grpc=$env:GRPC_INSTALL_DIR/bin/grpc_cpp_plugin.exe" greet.proto
    ```
   - greet.grpc.pb.cc
   - greet.grpc.pb.h
   - greet.pb.cc
   - greet.pb.h
   - ができていれば成功

## Visual Studio プロジェクト設定
任意のC++プロジェクトで上記で生成したプログラムが使える状態にする
1. ビルド設定をRelease x64にする（それ以外の場合上記のCMakeコマンドの変更が必要）
2. 上記で生成した*.cc, *.hをプロジェクトに追加
3. プロジェクトのプロパティ設定
   1. ビルドイベント>ビルド前のイベント>コマンドライン
      - 上記のprotocコマンドを生成するバッチファイルなどを作ってビルド前にprotoファイルのコンパイルを行う
   2. C/C++>追加のインクルードディレクトリ
      - $(GRPC_INSTALL_DIR)\include
   3. リンカー>追加の依存ファイル
      - $(GRPC_INSTALL_DIR)\lib\*.lib

## コード
適当な生成AIにprotoファイルを渡せばそれなりに動くサンプルコードを作ってくれるので省略
laravel ✕ OAuth2.0 Socialiteライブラリを使ってユーザー情報取得するときのuser()メソッドの定義箇所

## 概要

laravelのライブラリのSocialiteにてアカウントの情報を取得する際に`Socialite::driver('google')->user();`のようなコードを記載する。
この`user()`の実装内容が知りたかったので定義箇所を調べてみた。

## 定義箇所

`vendor/laravel/socialite/src/Two/AbstractProvider.php`に定義されている。

```vendor/laravel/socialite/src/Two/AbstractProvider.php
    /**
     * {@inheritdoc}
     */
    public function user()
    {
        if ($this->user) {
            return $this->user;
        }

        if ($this->hasInvalidState()) {
            throw new InvalidStateException;
        }

        $response = $this->getAccessTokenResponse($this->getCode());

        $user = $this->getUserByToken(Arr::get($response, 'access_token'));

        return $this->userInstance($response, $user);
    }
```

これっぽい

## 付録

どのように定義場所を見つけたのかの流れをざっくり記しておく。

1. ライブラリ側の実装のハズなのでvendor/laravel/直下をみてライブラリ名のフォルダがあるか確認socialiteというフォルダを発見
1. vendor/laravel/socialite/の中にsrcフォルダを発見、この中におそらくライブラリの実装コードが入ってそう
1. vendor/laravel/socialite/src/には更にフォルダがあるがそんなにファイルは多くないのでファイル名だけで関連してそうなものを当たりをつけてみる
1. 関連してそうなのは下記
    1. `vendor/laravel/socialite/src/Contracts/User.php` （インタフェースの定義のみなので直接の関係はなさそう）
    1. `vendor/laravel/socialite/src/One/User.php` （クラス名的に関係してそうだけど内容はあまり無いので後述する継承元クラスを次に確認）
    1. `vendor/laravel/socialite/src/AbstractUser.php` （ん〜これもライブラリ用のユーザーオブジェクトの定義をしているだけっぽい、自分が見たいのは`user()`の中身なのでちょっと違う、`vendor/laravel/socialite/src/One/User.php`で定義されているクラスを呼び出しているファイルをgrepコマンドで`vendor/laravel/socialite/src/`直下を探索、`\Laravel\Socialite\One\User`を検索）
    1. `vendor/laravel/socialite/src/One/AbstractProvider.php`で`user()`が定義されていた
    1. あれ？でもこっち`vendor/laravel/socialite/src/Two/AbstractProvider.php`にも`user()`が定義されている
    1. 両方の`user()`の最初の処理で`dd('hoge')`と`dd('fuga')`のように見分けがつく`dd()`を仕込んで`Socialite::driver('google')->user()`のコードが実行されるようなアクションを起こしてみよう
    1. `vendor/laravel/socialite/src/Two/AbstractProvider.php`こっちだったわ

あとからちょっと調べたら

- `vendor/laravel/socialite/src/One/`直下はAuth1.0用
- `vendor/laravel/socialite/src/Two/`直下はAuth2.0用

らしい
Pythonスクリプトを一つにまとめる！pyCombinerの紹介と使い方


---

# Pythonスクリプトのメンテナンスを助ける、新しいツール `PyCombiner` のご紹介

Pythonで複雑なスクリプトを作る際、コードを複数のファイルに分割するのは常に行われるベストプラクティスです。しかし、そのような複数ファイルで構成されたスクリプトを利用者に配布するには、それなりの誤解や経路の問題が生じやすくなります。

ここで、`PyCombiner`の出番です。

`PyCombiner`は、Pythonの複数のモジュールやファイルをスマートに解析し、最終的に1つの`.py`ファイルにまとめるCLIツールです。

---

## 他ツールとの比較

| 利用シーン       | ツール            | 出力形式        |
| ----------- | -------------- | ----------- |
| 自作コードの合体    | **PyCombiner** | `.py`ファイル   |
| pipパッケージの合体 | `stickytape`   | `.py`ファイル   |
| 実行可能zip     | `zipapp`       | `.pyz` ファイル |
| 単独実行ファイル    | `PyInstaller`  | `.exe` ファイル |

`PyCombiner`は、`PyInstaller`や`stickytape`に比べると簡単で軽量です。`.exe`のようなバ若さはなく、結果は1つの`.py`にまとまります。

---

## インストール

```bash
pip install pycombiner
```

---

## クイックスタート

仕様を知りたい場合は、編集者が提供しているデモプロジェクトを使用して簡単にテストできます:

### Step 1: GitHubからデモをクローン

```bash
git clone https://github.com/GWillS163/pyCombiner.git
cd pyCombiner/tests/examples/deep_demo
```

### Step 2: `pycombiner` の実行

```bash
pycombiner main.py
```

### Step 3: 結果を確認

```bash
dir

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        2025/06/02     17:23                subdir
-a----        2025/06/02     17:23            270 main.py
👉　-a----    2025/06/02     17:24            308 main20250602_172431_combined.py　👈
-a----        2025/06/02     17:23             62 module1.py
-a----        2025/06/02     17:23              0 __init__.py
```

実行結果は同じフォルダ内に出力され、合体されたPythonファイルを確認できます。

---

このように `PyCombiner` は、スクリプトの開発・管理のメンテナンス性を高めながら、配布方法を簡略化することを目指した、非常に有用なツールです。

## ✨ Credits & License

* Created by [GWillS163](https://github.com/GWillS163)
* Open source under [MIT License](LICENSE)
Reactのプロジェクトをgithub pagesに自動デプロイする

# ReactアプリをGitHub Pagesで公開する方法【初心者向け】

##  使用するツール・環境

- Node.js / npm
- React
- GitHub アカウント

##  手順概要

1. リポジトリをGitHubに作成
2. Reactアプリに `gh-pages` パッケージを導入
3. `package.json` を設定
4. アプリをビルドしてデプロイ
5. GitHub Pagesで公開設定


### 1. リポジトリをGitHubに作成
ここは省略

### 2. `gh-pages` をインストール
リポジトリをクローンし、プロジェクトのルート直下で以下を実行します。

```bash
npm install gh-pages --save-dev
```

### 3. `package.json` を編集

`package.json`のなかに`homepage` を追加

GitHubのユーザー名とリポジトリ名に置き換えて設定します。

```json
"homepage": "https://ユーザー名.github.io/リポジトリ名"
```
`scrips`のなかに以下を追加

```json
"scripts": {
  "predeploy": "npm run build",
  "deploy": "gh-pages -d build"
}
```

### `.github/workflows/deploy.yml`を作成
プロジェクトのルートで

```bash
mkdir -p .github/workflows && touch .github/workflows/deploy.yml
```
を実行。

作成された`deploy.yml`のなかには
```yaml
name: Deploy React App to GitHub Pages

on:
  push:
    branches:
      - main  # ← 必要に応じて変更（開発しているブランチ）

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18

      - name: Install dependencies
        run: npm install

      - name: Deploy to GitHub Pages
        run: npm run deploy
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
を書き込みます。適宜開発ブランチを選択してあげてください。

### `github pages`の設定

GitHubでリポジトリを開いたら

「Settings」 → 「Pages」

「Build and deployment」→ 「Source」を「Deploy from a branch」に設定

「Branch」は gh-pages を選択

### おわり
これでmain ブランチにpushすると、GitHub Actionsがビルド→gh-pagesブランチにデプロイしてくれるようになります。
【問題解決】変更セットの作成時に「Lightning Web Component」が見つからない

変更セットの作成時に「Lightning Web Component」が見つからなくて困りました。
原因が分かったので、解決方法を共有します。

# 問題発生
変更セットの作成時に「Lightning Web Component」が見つかりませんでした。
「Lightning Web コンポーネントバンドル」を選択すると

```
Unexpected error loading components:
Error: Cannot determine components list. Use standard changeset items selection (1).
```
となります。
![スクリーンショット 2025-06-03 132758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3255462/c7951ba2-cacb-478f-80ee-7ddf6898df70.png)


# 解決方法
画面に表示されている「ORGanizer Change Set Helper」の機能を停止したら、
作成した「Lightning Web Component」が表示されました。
※「Close Plugin」ボタンを押下
シークレットモードでブラウザを操作しても、「Lightning Web Component」が表示されます。
「ORGanizer」というブラウザの拡張機能が原因でした。
https://organizer.enree.co/faq.html#changeset

# 参考文献
下記の投稿のおかげで、問題の原因がわかりました。
ありがとうございました。
https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D53A00004o4WjVSAU
プロデル、調査 その19

# 概要
プロデルが、CLRらしいので、調べて見た。
サンプルにハノイの塔、見つけたのでやってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4d793130-1ba1-4c98-b517-ef0605505ecd.png)

# サンプルコード

```

円盤数 = 4
解法 = {}
円盤数だけ｛1, 2, 3｝をハノイする
メイン画面を表示する
待機する

メイン画面とは
    	+塔群 = {}
    	+塔位置 = {120, 240, 360}
    	+移動番号 = 0
    	ウィンドウを継承する
はじめの手順
    	初期化する
    	タイマー１というタイマーを作る
    	タイマー１の間隔を2500に変える
    	キャンバス1へ線を描いて棒Aとする
        	その始点は｛塔位置(1),150｝
        	その終点は｛塔位置(1),250｝
        	その線色を灰色に変える
        	その太さを10に変える
    	キャンバス1へ線を描いて棒Bとする
        	その始点は｛塔位置(2),150｝
        	その終点は｛塔位置(2),250｝	
        	その線色を灰色に変える
        	その太さを10に変える
    	キャンバス1へ線を描いて棒Cとする
        	その始点は｛塔位置(3),150｝
        	その終点は｛塔位置(3),250｝
        	その線色を灰色に変える
        	その太さを10に変える
    	キャンバス1へ四角形を描いて底板とする
        	その位置と大きさは｛20,250,440,30｝
        	その太さを0に変える
        	その背景色を灰色に変える
    	キャンバス1へ文字を描いて回数ラベルとする
        	その位置は｛300,10｝
        	そのフォントを「メイリオ」に変える
        	その文字色を緑色に変える
        	その文字サイズを20に変える
    	スタックを作って塔群(1)とする
    	スタックを作って塔群(2)とする
    	スタックを作って塔群(3)とする
    	長さは、120
    	円盤数回数にカウントして繰り返す
        	キャンバス1へ四角形を描いて円盤とする
            		その位置と大きさは｛棒Aの横 - 長さ / 2,  底板の縦 - (塔群(1)の要素数 + 1) * 20, 長さ, 20｝
            		その背景色は、HLS（{(数 * 360 / 円盤数) % 360，0.8，0.6}）
        	塔群(1)に円盤を積む
        	長さは、長さ * 0.7
    	そして
終わり
初期化する手順
      	この実質大きさを｛796,473｝に変える
      	この内容を「ハノイの塔」に変える
      	初期化開始する
	      	自動ボタンというボタンを作る
            		その位置と大きさを｛293,23,112,34｝に変える
            		その内容を「自動」に変える
            		その移動順を4に変える
        	前ボタンというボタンを作る
            		その位置と大きさを｛33,23,112,34｝に変える
            		その内容を「戻る」に変える
        	次ボタンというボタンを作る
            		その位置と大きさを｛161,23,112,34｝に変える
            		その内容を「進む」に変える
            		その移動順を1に変える
        	キャンバス1というキャンバスを作る
            		その位置と大きさを｛0,0,796,473｝に変える
            		その移動順を2に変える
            		そのドッキング方向を「全体」に変える
        初期化終了する
        この設計スケール比率を｛144,144｝に変える
終わり
次ボタンがクリックされた時の手順
        移動番号が解法の個数なら返す
        移動番号を増やす
        操作は、解法(移動番号)
        塔群(操作(2))から取り出して塔群(操作(3))へ積む
        反映する
終わり
前ボタンがクリックされた時の手順
        移動番号が0なら返す
        操作は、解法(移動番号)
        塔群(操作(3))から取り出して塔群(操作(2))へ積む
        移動番号を減らす
        反映する
終わり
反映する手順
        回数ラベルの内容は「[移動番号]回目」
        塔番号は、1
        塔群のすべての塔についてそれぞれ繰り返す
            	番号は、1
            	塔の全要素のすべての円盤についてそれぞれ繰り返す
                	円盤の位置は｛塔位置(塔番号) - 円盤の幅 / 2, 底板の縦 - 170｝
                	0.2秒待つ
                	円盤の位置は｛塔位置(塔番号) - 円盤の幅 / 2, 底板の縦 - (塔の要素数 - 番号 + 1) * 20｝
                	番号を増やす
            	そして
         	塔番号を増やす
        そして
終わり
自動ボタンがクリックされた時の手順
        タイマー1が動作中なら
            	タイマー1を停止する
        そうでなければ
            	移動番号が解法の個数なら
                	移動番号は、0
                	塔群は、塔群から１番目と３番目を交換したもの
            	そして
            	タイマー1を開始する
        そして
終わり
タイマー１が時間になった時の手順
        次ボタンがクリックされた
        移動番号が解法の個数なら
            	タイマー1を停止する
        そして
終わり
終わり

【値:整数】だけ【塔:整数の配列】をハノイする手順
    	値>0なら
        	値-1だけ｛塔(1), 塔(3), 塔(2)｝をハノイする
        	解法に{値, 塔(1), 塔(3)}を加える
        	値-1だけ｛塔(2), 塔(1), 塔(3)｝をハノイする
    	そして
終わり





```

以上。
PowerAutomateでCSVから複数行テキスト要素を抜き取りたい！

## はじめに
皆様、PowerAutomate使ってますでしょうか？
最近、自分はPowerAutomateを使って
- 日次で届くCSVをセルごとに抜き出してMicrosoft Listに登録する
- Microsoft Listへの登録をトリガーに情報をTeamsチャネルに送信する

というワークフローを作りました。
この時、大体は以下の記事を参考にしたのですが、今回は複数行テキストの要素を抜き出す必要がありました。そこで、「何が問題なのか？」「どうやって実現したのか？」と、苦労話を書いていけたらなと思います。

https://jpdynamicscrm.github.io/blog/powerautomate/Import-Csv-With-Standard-Connectors/

## CSVの要素抜き出しにおける通常と今回の違い
### そもそも...CSVって？
CSVと聞くと、「エクセルで開くことが出来る」・「セルごとに情報が入っている」ので、Excelファイルとあまり大差ないファイル形式なのかなというイメージを自分自身は抱いていました。
しかし、このイメージは全く見当違いでした笑。CSVファイルはテーブルをテキスト化したファイルで、テーブルの各行を改行コード (\n)で区切り、各列をカンマで区切ることで、1要素を表している構成でした。
CSVをメモ帳などで開くとこうなっています。(cell-ijのiは行番号、jは列番号を表しています)
```
cell-11,cell-12,cell-13,...\n
cell-21,cell-22,cell-23,...\n
...
```

このデータの場合は、PowerAutomateで以下の手順で、要素の分割が可能です！
1. `\n` をもとに、CSVデータを行データに分割する
1. `,`をもとに、行データを1つ1つに分割する

### 今回のCSVの形式：複数行のテキストがセル要素として存在する
しかし、今回のCSVは以下のようになっています。
このデータでは、2列目のデータが改行を含めたテキストになっています。
```
cell-11,cell-\n
12,cell-13,cell-14,...\n
cell-21,cell-\n
22,cell-23,cell-24,...\n
...
```
この場合、`\n` をもとに行要素を分割すると
1行目：`cell-11,cell-`
2行名：`12,cell-13,cell-14,...`
となってしまい、正確に行要素の分割が出来なくなってしまいます。

今回は、このような場合でも、1行ごとに要素を抜き出すことを目指します！

## 対応：行データの最後を全て同じ言葉にする！
今回のケースでは、`\n` を行分割の文字としているため、問題が発生していました。そこで、各行の最後の文字を統一し、これを行分割の文字としました。
つまり、以下のようなファイルになっています。
```
cell-11,cell-\n
12,cell-13,cell-14,...,行を分割しますよ！\n
cell-21,cell-\n
22,cell-23,cell-24,...,行を分割しますよ！\n
...
```
そして、PowerAutomateの行分割は、次の手順で行いました。以下、使用したアクションとアクションで使用した要素について記載します！
**※「CSVファイルコンテンツ」とは、CSVファイルで、ヘッダを無くした物です！**

**1. 行分割文字を定義する (アクション：変数を初期化する)**
値は、もしかしたらシンプルに「行を分割しますよ！\n」としても良かったかもですね...。
| 要素 | 値 |
|:-:|:-:|
| 名前 | 行分割文字 |
| 種類 | 文字列 |
| 値 |  `decodeUriComponent('「行末の文字+\n」をエンコーディングした値')` |

**2. 行配列を定義する (アクション：変数を初期化する)**
| 要素 | 値 |
|:-:|:-:|
| 名前 | 行配列 |
| 種類 | アレイ |
| 値 |  空欄 |

**3. 行配列を設定する (アクション：変数を設定する)**
| 要素 | 値 |
|:-:|:-:|
| 名前 | 行配列 |
| 値 |  `split(variables('CSVコンテンツ'), variables('行分割文字'))` |

やや力技ではありますが笑、後は、記事と同じ流れで設定すると、複数行テキストを1セルとして抜き出すことが可能になります！

## まとめ
今回は、PowerAutomateでCSVファイルの複数行テキストを1セルとして抜き出したいときの力技を紹介しました。
他にもPowerAutomateは生成AIを使用して、PDFを読み込んで文字をデジタル化したり、デジタル化した文字を抽出することも出来ました！それについてはまたの機会にお話しできればと思います～！
それでは、よき自動化ライフを（）
レンダリングとコンパイラとインタプリタの違い

レンダリングエンジンとコンパイラの仕組みの違い


はい、レンダリングエンジンとコンパイラは、どちらも「何かを別の形式に変換する」という点で似ていますが、その目的と対象が大きく異なります。

レンダリングエンジン

目的: ウェブページのソースコード（HTML、CSS、JavaScriptなど）を解析し、実際にユーザーが見ることができる視覚的な表現（ピクセル）に変換して画面に表示することです。
主な処理対象:
HTML: ドキュメントの構造を解析し、DOM (Document Object Model) ツリーを構築します。
CSS: スタイルシートを解析し、CSSOM (CSS Object Model) ツリーを構築し、DOMにスタイルを適用します。
JavaScript: JavaScriptエンジン（例: V8）に処理を渡し、DOMやCSSOMを動的に変更した結果を反映させます。
画像、動画などのリソースも扱います。
出力: 画面に描画するためのピクセル情報です。
動作: ウェブページが読み込まれるたびに、またはJavaScriptによってDOMが変更された際などに動作します。逐次的に処理を進め、可能な限り早く画面に内容を表示しようとします。
コンパイラ

目的: あるプログラミング言語で書かれたソースコード全体を、コンピュータが直接実行できる形式（機械語やバイトコードなど）に変換することです。
主な処理対象: 特定のプログラミング言語のソースコード全体です。
出力: 実行可能なプログラム（バイナリファイルやバイトコードなど）です。
動作: プログラムを実行する前に行われます。通常、一度コンパイルが成功すれば、その後はコンパイル済みのプログラムを何度でも実行できます。エラーがあれば、コンパイルは途中で止まります。
仕組みの違いのまとめ

特徴	レンダリングエンジン	コンパイラ
主な入力	HTML、CSS、JavaScript、画像などウェブ関連のリソース	特定のプログラミング言語のソースコード全体
主な出力	画面のピクセル表現	実行可能なプログラム（機械語、バイトコードなど）
主な目的	ウェブページを視覚的に表示する	プログラムをコンピュータが実行できるように変換する
動作のタイミング	ウェブページの読み込み時や動的な更新時	プログラム実行前
処理の単位	ドキュメント全体、およびその変更に応じて逐次処理	ソースコード全体

Google スプレッドシートにエクスポート
例えるなら、

レンダリングエンジン は、レシピ（HTML）、飾り付けの指示（CSS）、調理の指示（JavaScript）を読み込んで、最終的な料理（ウェブページ）を食卓（画面）に出す料理人のようなものです。
コンパイラ は、外国語で書かれた小説（ソースコード）を、母語で書かれた小説（機械語）に翻訳する翻訳家のようなものです。翻訳が終われば、原文がなくても翻訳された小説を読むことができます。
金沢はいかがお過ごしでしょうか？何か他に知りたいことはありますか？






レンダリングとインタプリタはまた違うものですか？


はい、レンダリングとインタプリタは異なる概念です。

レンダリング (Rendering)

これは先ほど説明したように、ウェブページのソースコード（HTML、CSS、JavaScriptなど）を解析し、最終的にユーザーが見ることができる視覚的な表現（ピクセル）を画面に描画するプロセス全体を指します。
レンダリングエンジン（例：Blink、Gecko、WebKit）が行う一連の処理（HTML解析、CSS解析、レンダリングツリー構築、レイアウト、描画）を指します。
インタプリタ (Interpreter)

インタプリタは、プログラミング言語で書かれたソースコードを一行ずつ読み込みながら、その場で実行するプログラムです。
コンパイラのように、事前にソースコード全体を機械語などの実行可能な形式に変換するのではなく、実行時に解析と実行を同時に行います。
JavaScriptは、一般的にインタプリタ型の言語と見なされます（ただし、多くのJavaScriptエンジンはJust-In-Time (JIT) コンパイラを搭載しており、パフォーマンス向上のために一部コードをコンパイルします）。
違いのまとめ

特徴	レンダリング	インタプリタ
主な対象	ウェブページのソースコード（HTML、CSS、JavaScript）、画像など	プログラミング言語のソースコード
主な目的	ウェブページを視覚的に表示すること	プログラミング言語のコードを逐次的に実行すること
出力	画面のピクセル表現	プログラムの実行結果（変数への代入、関数の呼び出し、画面への出力など）
処理の単位	ドキュメント全体とその変更に応じて処理。最終的な出力は視覚的な表現。	ソースコードの一行ずつ。

Google スプレッドシートにエクスポート
JavaScriptとの関係

ウェブページのレンダリングプロセスの中で、JavaScriptはJavaScriptエンジン（インタプリタとJITコンパイラを含む）によって実行されます。JavaScriptはDOMやCSSOMを操作することで、レンダリングの結果を動的に変更することができます。

例えるなら、

レンダリング は、ウェブページという絵を描く行為全体です。
インタプリタ (JavaScriptエンジンの主要な部分) は、絵を描くための指示書（JavaScriptコード）を一行ずつ読んで、その指示に従って絵を変化させる人のようなものです。
金沢の午後のひととき、いかがお過ごしですか？他に何か気になることはありますか？
LD_LIBRARY_PATHを利用したフーキング方法


## 🔧 組込みやLinuxでのデバッグ・修正時に関数の値をすり替えたいとき

組込みやLinux開発では、以下のような理由で**関数の挙動を途中で変更**したくなる場面がよくあります：

* バグのある共有ライブラリを修正したい
* 既存のプログラムに「ちょっとだけ」機能を追加したい
* 実行中の特定関数の返り値を操作したい

こういうとき、よく使われるのが「**フック（Hooking）**」という手法です。

その中でも**一番手軽**なのが、`LD_LIBRARY_PATH`を使った方法です。

---

## 📌 LD\_LIBRARY\_PATHとは？

`LD_LIBRARY_PATH`は、Linuxで実行時に動的ライブラリ（`.so`）を探すための**検索パスを指定する環境変数**です。

簡単に言うと：

> 「おい実行ファイル、いつもの場所になかったらここ（指定したディレクトリ）も見てみてくれ！」

---

## 💡 シナリオ：ライブラリ関数のフック（すり替え）

以下のようなシナリオを想定します：

* `victim`という実行ファイルがある
* これは`real_lib`内の`greet()`という関数を呼び出す
* 私たちはこの`greet()`関数を\*\*偽物のライブラリ（`fake_lib`）\*\*で置き換え、
* 実行結果を改ざんしたい

---

## 📦 プロジェクト構成

```bash
git clone https://git.kudryavka.me/blog/ld_path_hack_demo.git
cd ld_path_hack_demo
```

```
ld_path_hack_demo/
├── CMakeLists.txt
├── fake_lib/
│   ├── CMakeLists.txt
│   └── mylib.cpp        👈 私たちが作った偽ライブラリ
├── real_lib/
│   ├── CMakeLists.txt
│   └── mylib.cpp        👈 victimが本来使っているライブラリ
├── victim/
│   ├── CMakeLists.txt
│   ├── main.cpp         👈 実行ファイル
│   └── mylib.h
```

---

## 🧪 目標：greet()関数の出力を以下のようにする

```cpp
// fake_lib/mylib.cpp
#include <iostream>
void greet() {
    std::cout << "❌ HACKED: This is the fake library!" << std::endl;
}
```

---

## 🛠️ ビルドと実行

```bash
# 1. ビルド
mkdir build && cd build
cmake ..
cmake --build .

# 2. 通常の実行
./victim/victim
# → ✅ Hello from the real library!

# 3. フック（すり替え）実行
mv real_lib/libmylib.so real_lib/libmylib_  # 本物ライブラリの名前を一時変更
LD_LIBRARY_PATH=./fake_lib ./victim/victim
# → ❌ HACKED: This is the fake library!
```

---

## 🔍 なぜすり替えが成功したのか？

`victim`実行ファイルは、起動時に`libmylib.so`を**動的リンク**で読み込もうとします。

このとき、`LD_LIBRARY_PATH=./fake_lib`を指定しているため、

* 動的リンカ（`ld.so`）はまず`fake_lib/libmylib.so`を探す
* それが見つかったため、そちらを使用
* 本物（`real_lib/libmylib.so`）は名前を変えたので無視される

結果、**偽の`greet()`関数が実行される**というわけです。

---

## 🛡️ この手法が悪用されたら？

例えば、SSL通信ライブラリ（例：OpenSSL）をこのようにすり替えれば、**暗号通信の平文を盗み見ることすら可能**になります。

---

## 📎 関連ツール

| コマンド                | 説明                  |
| ------------------- | ------------------- |
| `readelf -d <バイナリ>` | ELFの動的リンク情報を確認      |
| `ldd <バイナリ>`        | 使用されている共有ライブラリを一覧表示 |
| `patchelf`          | RPATHなどの修正に使用       |
| `objdump -p`        | ELFヘッダを分析           |