findOne()とfindOneAndUpdate()とでは、コールバックに返されるdocの階層が違うので気を付けよう

function(err, doc){
doc; //←findOne()の場合はこれがドキュメントのコピー。
doc.value; // ←findOneAndUpdate()で、updateされた方のドキュメントを受け取るように指定した場合はこれがドキュメントのコピー。docではないので、はまった。
}
そゆこと。簡単にはそゆこと。

socket.ioを使いたいならapp.listen()じゃだめさ

やあ子供たち。express勉強しているか。おじさんは勉強始めたばかりのくせにすぐこんなふうに上から目線のタイトルをつけた記事を書いちゃうんだからな。気を付けてくれよ。
さて今日はapp.listen()を使ってしまうと、socket.ioが使えなくなるという恐ろしい事実を知ったので緊急メモを残すぞ。

const express =require("express");
const app = express();
app.listen(80,()=>{
  console.log("app listening.. ");

const socketio = require("socket.io");
const io = socketio(server);
// emit, on, いくらやっても、、→→使えない!
});

io.sockets.on('connection', function (socket) {
  socket.on("tak",data=>{

  });
});

はい、これでサーバは立ち上がるだろうが、これではsocket.ioが使えなくなるんだね。え?エラー?いやいや何も出ないよ。ただソケット通信ができなくなるんだよ。いくらemitしてonで受け取ろうとしてもなしの礫さ。そして何十分も棒に振ることになるんだね。恐ろしいね。
ではどうすればよいか?まあ落ち着け、そうだからってexpressじゃsocket.ioが使えないぜって話でもないんだ。。

それはね、つまりexpress とsocket.io とを組み合わせて使いたい場合はね、以下のようにすることらしいぞ。

const express =require("express");
const app = express();
const http = require("http");
const server = http.createServer(app);
server.listen( 80, "127.0.0.1", ()=>{
  console.log("app listening.. ");
});

const socketio = require("socket.io");
const io = socketio(server);
// emit, on, いくらやっても、、→→使える!

io.sockets.on('connection', function (socket) {
  socket.on("tak",data=>{

  });
});

はいはい何をしたかというと、app.listen()ではだめで server.listen()を使っていきましょうということらしい。こうすればね、app.useとかapp.getとか普通に使えるしexpress使えるよ、しかもsocket.ioもちゃんと通信できる。
はい、ではなぜなのか。なぜapp.listen()ではだめで server.listen()ならsocket.ioが使えるようになるのか。
このことは本家サイト(●こちら)でも紹介されているが詳細説明はない。
そしてここでも(●リンク)いろいろ頑張ってみた人がいたが、腑に落ちる説明が見当たらない。ここの書込みではこのことをtrapと呼んでいる人もいて(1年前だよそんなに最近なのにね!)この案件は本当にtrapなんだよね。
では今日はこのあたりで。チャオ!

今いる場所でコマンドプロンプトを開いてくれるBATファイルを作ってみた

やあ子供たち。今日はタイトルの通りの内容のメモだよ。以下のコードをcmd_here.bat という名前にでもしたBATファイルとして保存して、任意のフォルダにコピーして、これを実行してみよう。すると、その場所に最初からいる状態でコマンドプロンプト画面が始まるぞ!

@echo off
cmd /k "cd /D %~dp0"

地味に便利じゃないかこれ。
では今日はここまでだ。チャオ!

express.static() を先回りして特定のファイルの返送処理を自分ロジックで上書きしよう。

やあ子供たち。
express.static()は便利な反面、実際には何をやってくれているのかがブラックボックスになっているとも言えるね。
例えばあるコンテンツページを表示した際に、pngを返した枚数だけカウントしたいだとか、jpegは禁止するだとか、動画は当然ストリーミングで返してくれてるよね、え?まさか全部メモリに読み込んだバッファを返してるの?何してくれちゃってるの?という具合に、単純にexpress.staticに任せきりにしたくない場合というのは多々あるはずだ。
そんなときは、「expressのミドルウェアは、記述した順番に実行される」ということを利用して、例えば「png」で終わるリクエストURLだけ捕まえてその中でやりたい処理をやり、そこでレスポンスを終わらせてしまえばいいだけのことさ。あるいはここで、pngきたよとかログに追記したり、そのpngに何かをして、返したり(何何?)、いろいろできるってわけ。
それをやってみた具体的なコードが以下だよ。 

app.get("/*png",(req, res)=>{
  console.log(req.url);
  console.log("i have captured png req before express.static does.");
  var path = __dirname + "/static_resources"+ req.url;
  console.log( path);
  fs.readFile(path, (err, data) => {
    if (err) {
      console.log("file read error");
      // res.end();
    }else{
      console.log("hi, and im gonna write and send png for my own, not express.static");
      res.writeHead(200, { "Content-Type": "image/png" });
      res.end(data, 'binary');
    }
  });
});
app.use(express.static("static_resources"));

気を付けなければいけないのは、コンテンツは、express.staticのベースパス(上記一番下の行で指定しているよ)の中に実際には配置されているわけなので、上記pngの処理の中で、ちゃんとこのベースパスも入れた正しいパスをfs.readFileには渡してあげなくちゃいけないよねってことさ。
じゃ今日はこの辺で。(expressを知らないNodeJSだけの国からやってきたおじさんの今日の気づきでした。)
チャオ!

GoogleSpreadSheetの日付入力ショートカット

やあ子供たち、Excelで日付をショートカットキーで一発入力するのは「Ctrl+;(セミコロン キー)」で、超便利なわけなんだが、GoogleSpreadSheetを使っているときに、日付を入力したいというわけでそれをやろうとすると、ブラウザなだけに、画面の表示倍率が上がっていってしまうので、「あー、だめか、無理なのか」と思ってそのまま放置してしまっていたのだが、ちゃんと調べてみるとなんと「Ctrl+:(コロン キー)」で、日付が入力できるぞ!ちなみにExcelで「Ctrl+:(コロン キー)」を押すと、現在時刻を一発入力できてしまうわけなので、じゃあGoogleSpreadSheetでは、現在時刻は入力できないのか?というと、そんなことはなく、現在時刻入力のショートカットキーはずばり「Ctrl+Shift+:(コロン キー)」で入力が出来るぞ!

NodeJSだけでダウンロードサイトを作る

やあみんな。NodeJS楽しいよねまじで。
今日はおじさんはExpressとか使わずにNodeJSだけでファイルをダウンロードできるサイトを構築するための最小限コードをメモしようと思うぞ。(Expressを使っているお友達はres.download()が使えるのでこの記事に用はないはずさ。この記事に用があるのはきっと何か特殊な事情があるお友達だけだと思ってる。(ようこそ!そういうお友達!おじさんもみんなの仲間だよ!))
それではさっそくやっていきましょう。

●まずはユーザーの目に触れる表側。サイトのページを作ろう。
例えば以下のようなHTMLを用意しよう。(部分によってコメントの文法表記が違うから面白いとおもうのはおじさんだけかな?(笑)青い字の部分な。)

<html lang="ja">
<meta charset="utf-8">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control"content="no-cache">
<head>
<style>
  /* スタイルシートコードを記述 */
</style>
</head>
<body>
  <!--HTML部品を設置-->
  <h1 id="hello">My公式サイト</h1>
  <a href="/hello_dlreq" >hoge_file.7z(最新版)</a>
  <script type="text/javascript">
  // 必要に応じてプログラムを記述
  </script>  
</body>
</html>

これを、some_index.htmlとして保存しよう。

●次に裏側のしかけ。サーバーサイドを記述しよう。
さあそして、サーバーにリクエストが来た場合の処理を記述した、サーバーサイドjavascriptのプログラムを書いていこう。それは以下のようなものになるよ。

const http = require('http');
const server = http.createServer();
const fs = require("fs");
server.on("request", (req, res) => {
    if (req.url.endsWith('/')) 
    {
      // 用意したHTMLファイルを描画
      fs.readFile("./some_index.html", function(e, buff){
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(buff.toString());
        res.end();
      });
    }
    else if (req.url.endsWith('_dlreq')) 
    {
      // some_index.html中の<a>タグリンクが押された時にダウンロード開始してあげる処理
      // 日本語ファイル名もいけるかな?→それは試してみてくれよな!
      var FileName = "hoge_file.7z";
      res.setHeader('Content-Disposition', 'attachment;filename*=UTF-8\'\'' + FileName);
      var filepath1 = __dirname + '/some_folder/'+FileName;
      fs.createReadStream(filepath1).pipe(res);;
    }
});
server.listen(3000, () => console.log('Server http://localhost:3000'));

これを、some_server.js として保存しよう。
あとは、some_folderというフォルダを作成し、その中に、みんなが今ダウンロードさせたいと思っているファイル、hoge_file.7zを置こう。
フォルダ構成はこんな感じになるぞ。

│ some_index.html
│ some_server.js
└─some_folder/
        hoge_file.7z

はい!まずは以上!。どうだえらくシンプルでまさに最小コードという感じじゃないかこれ。さらに説明が必要だと感じたときにはまた追記したいと思います。
ではまたな、チャオ!