かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Mac デスクトップを iCloud 同期しているときの TIPS

昨年末から G's Academy という自分のプロダクトを作れるようになろう的なスクールでプログラミングのチューターをしています。
チューターをしている中で意外なトラップを発見したのでメモとして残しておきます。

Mac デスクトップを iCloud 同期設定をしているとパスが通らない問題

MaciCloud でデスクトップの同期設定をしているマシンで作業ファイルをデスクトップに置いて作業していると諸々パスが上手く通らないケースが発生します。

例えば firebase-tool を npm install -g でグルーバルインストールしているような時、デスクトップの作業ディレクトリで firebase コマンドを叩いても irebase: command not found になってしまうとか、npx create-react-app で作成した React アプリで npm run start した時にパッケージのエラーが表示されて起動しないとか、git をインストールしたのに git コマンドが無いと言われ続けるが発生しました。

原因としてはデスクトップが iCloud 同期されているので、ターミナルが今見ている作業ディレクトリがマシンのローカルなのか iCloud 上なのか判別できなくなて マシンローカルにインストールされている node や npm, homebrew などへのパスが通らない状態になってエラーが発生しているのかなと感じました。
自分がチューターをしていた中では npm まわりのエラーが殆どでしたが恐らくローカルマシンとのパスが通らなくなるので他の言語でも謎のエラーが発生するだろうなと思っています。

確か iCloud のデフォルトでデスクトップの同期が ON になっていたと思うので、特にプログラミングはじめました!プログラミング始めるために Mac 買いました!って方はハマる可能性の罠かなとも思います。

解決方法

解決方法はシンプルで「Macではデスクトップを開発ディレクトリにしない(iCloud 同期してる場合)です。
Mac のデスクトップのフォルダを VSCode で開いていてターミナルでコマンド打ったらよく分からないエラーが出たという時は iCloud の同期を疑ってみてみてみてください。

おわり。


[参考]

これは PATH が通らないときの TIPS

FLYING TIPS

FLYING TIPS

  • 発売日: 2021/03/24
  • メディア: MP3 ダウンロード

JavaScript, Node.js 先に作っておいた変数を named export したい

default exports は好きな名前で import できてしまうから極力 named exports / import にしたほうが良いと教えてもらったので、先に変数が作られてる場合どうするんだろう?と思い調べて見たメモ。

ESModules の named exports

exports

// foo.ts
export const foo = 'Foo!';

import

import { foo } from './foo'

ESModules の default exports

exports

// app.ts
import express = require('express');
const app: express.Express = express();

export default app;

import

import app from './app'

default exports は好きな名前で import できる

import myapp from './app'
myapp; // => express.Express

先に作っている変数を named exports したい

// app.ts
import express = require('express');
const app: express.Express = express();
app.use(...); 
// … 色々処理

export app;
// => Error: Declaration or statement expected.

これはDeclaration or statement expected. エラーになる。

export { } で named exports することができる

// app.ts
import express = require('express');
const app: express.Express = express();
app.use(...); 
// … 色々処理

export { app };

import

import { app } from './app';

₍ ᐢ. ̫ .ᐢ ₎👌

as を使えば名前を変えてnamed exports することもできる

// app.ts
import express = require('express');
const app: express.Express = express();

export { app as myapp };

import

import { app } from './app';
// => Error: Module '"./app"' declares 'app' locally, but it is exported as 'myapp'.

TypeScriptでは myapp で exports されているけど?というエラーを表示してくれる。
₍ ᐢ. ̫ .ᐢ ₎👌

default exports は default という特別な名前を付けた named export だった。

export default app;

これは下記と同じ意味

export { app as default };

e.g.

// app.ts
import express = require('express');
const app: express.Express = express();

export { app as default };

import

import { app } from './app';
// => Error: Module '"./app"' has no exported member 'app'. Did you mean to use 'import app from "./app"' instead?

TypeScriptでは import app from "./app" では?というエラーを表示してくれる。
₍ ᐢ. ̫ .ᐢ ₎👌

import

import app from './app';
// 👌

₍ᐢ •̥ ̫ •̥ ᐢ₎‪ 完全に理解した!

感想

import / exports 周り完全に雰囲気で使っているのでチョクチョクあれ?どうやるんだっけ???になってます。
ESModules と CommonJS の import / export, require / module.exports いつかちゃんと調べようと思いつつ数百年が立ってしまった… そして未だに雰囲気でしか理解してない。。。

TypeScript まだよわよわなんで頑張っていきたい。
チョットづつエラーも読めるようになってきた。


[参考]

ハンズオンNode.js

ハンズオンNode.js

  • 作者:今村 謙士
  • 発売日: 2020/11/17
  • メディア: 単行本(ソフトカバー)

Node.jsデザインパターン 第2版

Node.jsデザインパターン 第2版

Firebase Cloud Firestore で複数の OrderBy で 9 FAILED_PRECONDITION: The query requires an index なエラーになった

Cloud Firestore からデータを取ってこようとしたら次のようなエラーが返ってきた。

{
  error: {
    code: 9,
    details: "The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/<projectName>/firestore/indexes?...",
    message: "9 FAILED_PRECONDITION: The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/<projectName>/firestore/indexes?...",
    metadata: …
  }
}

9 FAILED_PRECONDITION なエラーになるコード

const db = admin.firestore();

const snapshot = await db
  .collection(COLLECTION)
  .orderBy('score', 'asc')
  .orderBy('createAt', 'asc')
  .get();

どうやら orderBy() が複数個あるとエラーになってしまうようでした。

Cloud Firestore にインデックスが作成されてないとエラーになる

エラーを見ていると The query requires an index. You can create it here: https://console.firebase.google.com/... と書かれていました。
エラーに続く URL にアクセスすると Firebase コンソールから Cloud Firestore にインデックスを作成するか聴かれるモーダルが表示されます。そのまま作成ボタンを押すとインデックスが作成されます。

firebase Cloud Firestore console

インデックスのビルドに少し時間がかかりますが、ステータスが 有効 になればインデックスが有効になり先の 9 FAILED_PRECONDITION になっていたクエリが実行できるようになりました。

インデックスが必要だと分かっている場合は、コンソールから前もってから作成しておくのが良さそうです。
インデックスが全く作成されていないプロジェクトなら Cloud Firestore のインデックス タブを選択して インデックスを作成ボタン から作成することができます。

firebase Cloud Firestore console

所管

複数のフィールドで並べ替えを行うこともできます。たとえば、州で並べ替え、各州の中で人口の降順で並べ替える場合は、次のようにします。

citiesRef.orderBy("state").orderBy("population", "desc");
cf. Order and limit data with Cloud Firestore  |  Firebase

公式ドキュメントに orderBy() を複数使う例が載っていて、そこにインデックスが必要なことが書かれていなかったので、そもそも Firestore に接続できてないのか?なども疑ってハマってしまいました。
Firebase のドキュメント総じて分かりにくい気がしてるのは僕だけ?
そして作成されたインデックスの削除の方法が分からない…


[参考]

ナイン (講談社文庫)

ナイン (講談社文庫)