Firebase CLI の init 後の初期状態では Cloud Functions 関連のファイルは以下となっているはずです。(TypeScript の場合)
└ functions/
├ その他ファイルたち
├ lib/
└ src/
└ index.ts
あとは index.ts
にトリガー関数を書いていけばそれで完成ではありますが、トリガーの数をそれなりに作成する場合は、ファイルを分割したい気持ちに駆られることは間違いないですよね。
Firebase CLI の init 後の初期状態では Cloud Functions 関連のファイルは以下となっているはずです。(TypeScript の場合)
└ functions/
├ その他ファイルたち
├ lib/
└ src/
└ index.ts
あとは index.ts
にトリガー関数を書いていけばそれで完成ではありますが、トリガーの数をそれなりに作成する場合は、ファイルを分割したい気持ちに駆られることは間違いないですよね。
Firestore のデータ型の1つに Timestamp 型があります。これは Firestore 独自の型です。
Timestamp が持っている toDate()
メソッドを呼び出すと、JavaScript の Date 型に変換することができます。クライアント側でデータを取得した後、データを操作する際にまず toDate()
を呼び出すというのはよくある動きだと思います。
例えばローカルのエミュレータ環境の Firestore へシードデータを流す際、シーディングの初期化処理としてデータを全削除したいというシチュエーションはよくあると思います。
...Firestore の苦手とする部分として複雑な検索条件をもとにデータを取得するのが困難です。
選択肢としては上記が考えられます。
...Parameters<typeof (function name)>
const greet = (name: string, word: 'Hello' | 'Good Bye') => {
return `${word}, ${name}!`;
};
type Args = Parameters<typeof greet>; // [name: string, word: "Hello" | "Good Bye"]
type firstArg = Args['0']; // string
type secondArg = Args['1']; // "Hello" | "Good Bye"
ReturnType<typeof (function name)>
const getUser = () => ({
name: 'Alice',
age: 20,
sex: 'female',
hasPhone: true,
friends: ['Bob', 'Charlie', 'David'],
school: {
name: 'Awesome University',
major: 'cs',
},
});
type User = ReturnType<typeof getUser>;
// {
// name: string;
// age: number;
// sex: string;
// hasPhone: boolean;
// friends: string[];
// school: {
// name: string;
// major: string;
// };
ReturnType<typeof (function name)> extends Promise<infer T> ? T : never
ReturnType<typeof (function name)> extends PromiseLike<infer T> ? T : never
const getUser = async () => ({
name: 'Alice',
age: 20,
sex: 'female',
hasPhone: true,
friends: ['Bob', 'Charlie', 'David'],
school: {
name: 'Awesome University',
major: 'cs',
},
});
type User = ReturnType<typeof getUser> extends Promise<infer T> ? T : never;
// {
// name: string;
// age: number;
// sex: string;
// hasPhone: boolean;
// friends: string[];
// school: {
// name: string;
// major: string;
// };
補足
...typeof xxx[number]
const names = ['Alice', 'Bob', 'Charlie', 'David'] as const;
type Names = typeof names[number]; // "Alice" | "Bob" | "Charlie" | "David"
keyof typeof xxx
const favoriteColors = {
alice: 'cyan',
bob: 'magenta',
charlie: 'yellow',
david: 'black',
} as const;
type FavoriteColors = keyof typeof favoriteColors; // "alice" | "bob" | "charlie" | "david"
typeof xxx[keyof typeof xxx]
本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...本記事は、本記事投稿時点の Human Interface Guidelines - iOS を日本語訳したものです。DeepL で機械翻訳を行った後、誤訳が見受けられた際には修正を加えています。
https://developer.apple.com/design/human-interface-guidelines/
...デザインとして取り決めを設定し共通認識をもたせたりする必要がある場合、デザインではガイドラインを定め運用する。 ユーザビリティ、ヒューマンインターフェース、コンピュータアクセシビリティなどを高めるため、情報デザイン、ウェブデザインの分野などで BTRON のように初めて使用するアプリケーションであっても混乱がないよう、メニューの並び順なども規格化し、多言語の利用についても考慮されたデザインガイドラインが既定されている。フォントなどは Roboto などのように Android や Chrome OS のシステムフォントに採用されており、マテリアルデザインのデザインガイドラインでも利用が推奨されている。 アップルではデザインガイドライン「Aqua Human Interface Guidelines」を設けこれに従ったレイアウトが容易に行えるようになっている。
...
*完全な自己整理用の記事です。
プロダクトのインフラをリプレースするため、リプレース前の構築環境を記録しておく。
本当は diagrams.net (Drow.io) を使ってやりたいけれど省力化
...万が一、削除してしまった時のために .zshrc
をここにメモしておく。それだけ。
保存という意味では GitHub にあげておけば良いのだが、そんなことをするまでもないと思ったのでここに記録。(私の中だと、ブログ記事よりも GitHub の方がより重要な資産を置く場所という感覚があるのですが、普通逆ですかね?)
...作業が発生した時に毎回毎回コマンドをググっている気がしたので、ここにメモしておく。
(これは自分用のメモです。類似の良質な記事は他にいくらでもあるので、恐らくそちらをご参照いただいたほうがよいです。)
...調べ物をしている時に、SemVer という単語を見かけました。見たことのない英単語だなと調べたところ、セマンティックバージョニングのことでした。
...学習記録として、記憶に残った内容をメモしておきます。
テスト駆動開発を原点から学ぶ
本書は、自分たちのコードに自信を持って開発を続けたいプログラマ、チームリーダー向けに、テスト駆動開発(TDD)の実践方法を解説した“Test-Driven Development By Example"の日本語版です。テスト駆動開発の考案者である Kent Beck 自身によって書かれた原典を、日本におけるテスト駆動開発の第一人者である和田卓人氏が訳しました。 テスト駆動開発とは単にテスト自動化を行うことではなく、ユニットテストとリファクタリングを両輪とした小さいサイクルを回すことで不確実性を制御し、不断の設計進化を可能にする手法であることを、実例を通して学ぶことができます。
...
このブログはこれまで WordPress で運用してきたのですが、今回、Hugo に乗り換えることにしました!
この記事は Hugo に乗り換えて初めて投稿する記事です!
皆さんがこの記事を読んでいるということは、無事に 引っ越しが完了したということですね!よかった!
...JavaScript の クラス について整理しておく。
JavaScript には class 構文があるがそれは単なるシンタックスシュガーであり、class を使わずともクラスを実現することができる。
...*書き殴り気味の完全な個人的メモです。
GAS はプリフライトをさばくことはできない。
Content-Type application/json
-> アウトContent-Type x-www-form-urlencoded
-> オーケーContent-Type text/plain
-> オーケーconst postReservation = async (name, email) => {
const endPoint = 'https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/exec';
const res = await fetch(endPoint, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, email }),
});
if (res.ok) console.log('okです!'); // しかし残念ながらokになることはありません。
};
const postReservation = async (name, email) => {
const endPoint = 'https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/exec';
const res = await fetch(endPoint, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `name=${name}&email=${email}`,
});
if (res.ok) console.log('okです!'); // okですね。
};
const postReservation = async (name, email) => {
const endPoint = 'https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/exec';
const res = await fetch(endPoint, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'text/plain',
},
body: `${name}&&&${email}`,
});
if (res.ok) console.log('okです!'); // okですね。
};
const doPost = (e) => {
const jsonString = e.postData.getDataAsString();
const data = JSON.parse(jsonString);
const { name, email } = data;
// 以降処理は続く...
};
const doPost = (e) => {
const name = e.parameters['name'][0];
const email = e.parameters['email'][0];
// 以降処理は続く...
};
const doPost = (e) => {
let text = e.postData.getDataAsString();
const [name, email] = text.split('&&&'); // フロントからリクエスト送る時に区切り文字を何にしているかによります
// 以降処理は続く...
};
GAS からのレスポンスは、成功だと 302 FOUND が返り、失敗だと 200 OK が返る。
...