TypeScript & React & Firebase で何かつくってみる5 Functions 2

書きやすい今のうちに 5日連続投稿のバッチをもらっておくか.
しかしこのバッチ,最大で365日連続投稿まであるのか... 絶対無理だな.

Functions で Firestore を操作する

これができなきゃ話にならない.

firebase-admin というパッケージを使えばいいらしい. 上記サイトでは 個別にインストールしているが, 既に入っていた. おそらく `firebase init functions` のタイミングで入ったのだろう. 

これを使って前回のトランプ52枚をシャッフルするAPIを作ってみた. シャッフルの実装はこちらのコードをコピペ.

トランプの束があり,これをシャッフルしたいとしましょう.束の中からランダムに 1 枚ずつ選び,束の隣に新しい束(シャッフル済の束)として重ねていきます.これが Fisher–Yates シャッフルです.

まさにそのものズバリ. ・・・スワップのやり方ちょっとカッコいいな.

index.ts

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp();
const fireStore = admin.firestore();
type Card = {
 name: string,
 color: string,
}
type Deck = {
 cards: Card[],
}
// https://chooblarin.github.io/post/array-shuffle
const shuffleArray = ([...arr]) => {
 let m = arr.length;
 while (m) {
   const i = Math.floor(Math.random() * m--);
   [arr[m], arr[i]] = [arr[i], arr[m]];
 }
 return arr;
};

export const shuffle = functions.https.onRequest((request, response) => {
 const deckRef = fireStore.collection('fields').doc('deck');
 deckRef.get().then(snapshot => {
   const deck = snapshot.data() as Deck;
   return deckRef.update({ cards: shuffleArray(deck.cards) });
 }).then(snapshot => {
   response.send('success');
 }).catch(err => {
   response.status(404).send('not found');
 });
});

参考記事では admin にクライアント同様 API キー を渡しているようだったが, 本家のドキュメントを見る限り必要なさそうだ. さすが admin.

あとはこの Function URL にリクエストを出すボタンを UI におけばいいはず.

画像1

ちなみにこの関数はHTTPメソッドを見ていない. おそらくどのメソッドを投げてもシャッフルするのだろう.

GETメソッドで関数実行なんて行儀悪い? まぁそういうのは後で考える.

Console エラー

Chromeのコンソールにエラーが出ている.

Access to fetch at 'https://XXXX' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

CORSの問題か.
CORSは厳密に言えば「通信を不許可」にしているのではなく, JavaScript がHTTPレスポンスにアクセスすることを禁止するだけだ.

つまり命令はサーバに届いている. だからクロスドメインでも関数が実行できているというわけだ.
ちゃんとしたサービスならセキュリティホールだな.

まさか localhost からのアクセスを許可するわけにもいかんし, Firebase Hosting 上に置いてしまえば発生しないだろうし, ひとまずほっとくことにする.

この記事が気に入ったらサポートをしてみませんか?