関連

プロミス化

utilモジュールのpromisifyでラップすることでPromise関数化できます。

const {promisify} = require('util');
const {readFile} = require('fs');

const readFilePromise = promisify(readFile);

readFile

あるディレクトリ上にあるファイルやディレクトリ名の一覧を取得します。

fs.readFile('./package.json', 'utf-8', (err, content) => {
  if (err === null) {
    // `Error: EISDIR: illegal operation on a directory` など
  }
  
  console.log(content);
  // {"name": "...", ...}
}

画像などを読み込む時は、utf-8指定はいりません。

fs.readFile('./static/logo.png', (err, content) => {
  // ...
}

readdir

あるディレクトリ上にあるファイルやディレクトリ名の一覧を取得します。

fs.readdir('.', (err, list) => {
  if (err === null) {
    // `Error: ENOENT: no such file or directory` など
  }
  
  console.log(list);
  // [
  //   '.git',
  //   ...
  //   'yarn.lock'
  // ]
}

依存

まず必要なパッケージをインストールします。

yarn add express express-jwt jsonwebtoken

トークンを生成

次の1行のコマンドで作れます。第2引数は復元に使うので覚えておきます。

node -e "console.log( require('jsonwebtoken').sign({value:'foo'}, 'a') )"
# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YWx1ZSI6ImZvbyIsImlhdCI6MTUzNTU2NDUyNH0.Mkz75dMlWnK2Y_8g7CGjqwLNvlc1pC3O8znGuUP5ZS8

復元を試します。第2引数は同じものを指定します。
ちゃんとオブジェクトが表示されてれば大丈夫。

node -e "console.log( require('jsonwebtoken').verify('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YWx1ZSI6ImZvbyIsImlhdCI6MTUzNTU2NDUyNH0.Mkz75dMlWnK2Y_8g7CGjqwLNvlc1pC3O8znGuUP5ZS8', 'a') )"                                                                         02:42:24
# { value: 'foo', iat: 1535564524 }

Expressサーバーで認証する

まずlocalhost:3333okとだけ返す所まで作ります。

const express = require('express');
const jwt = require('express-jwt');
const app = express();
app.use('/', /* jwt middleware が入る */ (req, res) => res.sendStatus(200));
app.listen(3333);

app.useの第2引数でexpress-jwtを使います。設定は次の通り。

  • secretは上記で発行した時に使ったものを

  • requestPropertyは、デフォルトではreq.userに値が入るのですが、今回はユーザー情報でも何でもないのでなんとなくreq.data

    • ちなみにresultPropertyreq.res.dataになるみたいですなんか知った)

  • getTokenはトークンの置き場を自分で探して見つけたトークンを返してます。今はAuthorizationだけ見ます

app.use(
  '/',
  jwt({
    secret: 'a',
    requestProperty: 'data',
    getToken(req) {
      if (
        req.headers.authorization &&
        req.headers.authorization.split(' ')[0] === 'Bearer'
      ) {
        return req.headers.authorization.split(' ')[1];
      }

      return null;
    }
  }),
  (req, res) => res.status(200).send(req.data)
);

実装は終わったで、あとはサーバーを建ててcurlで試してみます。レスポンスがjsonなら大丈夫です!

curl -H 'Authorization: Bearer {トークン}' http://localhost:3333
# {"value":"foo",...}

UnauthorizedError: invalid signatureの場合はどこかおかしいのでsecret合ってるかどうかなど確認しましょう。

基本

デフォルトタイプ

最初から以下タイプが定義されてるので、足りてるならsignale[TYPE]('メッセージ')の形で即使うだけです。

  • await

  • complete

  • error

  • debug

  • fatal

  • fav

  • info

  • note

  • pause

  • pending

  • star

  • start

  • success

  • warn

  • watch

  • log

以下はCLIでの使用例です。

const signale = require('signale');

const yargs = yargs.xxx(/* ... */);
// 引数情報表示
signale.info(`Port: ${argv.port}`);
// サーバー起動処理
signale.start('Server'));
// App起動処理
signale.start('App');
// ℹ  info      Port:  33322
// ▶  start     Server
// ▶  start     App

カスタムタイプ

SignaleClass をインポートして、自分用に作る必要があります。

const {Signale} = require('signale');

const signale = new Signale({
  types: {
    sake: {
      color: 'green',
      badge: '🍶',
      label: 'sake'
    }
  }
});
signale.sake('Kokuryu');
// 🍶  sake      Kokuryu

補足情報をつける

スコープ、

const appLogger = signale.scope('cli:app');
appLogger.start('listen');
// [cli:app] › ▶  start     listen

や現在のファイル名、

signale.config({displayFilename: false});
// [cli.js] › ✔  success   foo

またdisplayDateで年月日、displayTimestampで時分秒を出したりできます。

ログを表示しないようにする

開発中だけ出したいとかあると思います。
これは設定のstream/dev/nullに書き込むようにするとすべて捨てる事ができます。(以下はdev-nullパッケージを使ってます)

const devnull = require('dev-null');
const signale = new Signale({stream: devnull()});

一部だけ消したい時は各typesで設定する必要があります。例えば、「debugタイプ捨ててぇ」時

const devnull = require('dev-null');
const signale = new Signale({
  types: {
    debug: {
      stream: [devnull()]
    }
  }
});

👦🏻「ログファイルに出してぇ」

const signale = new Signale({
  stream: require('fs').createWriteStream('/tmp/foo.log')
});

コード

以下はとあるリポジトリのfoo.txtを取得しています。
取得した内はbase64でエンコードされてるのでデコードが必要です。

/**
 * `yarn add dotenv got`
 */

require('dotenv').config();
const got = require('got');

(async () => {
  const {body} = await got(
    'https://api.github.com/repos/:owner/:repo/contents/foo.csv',
    {
      json: true,
      headers: {
        accept: 'application/vnd.github.v3+json',
        authorization: `token ${process.env.TOKEN}`
      }
    }
  );

  const decodedContent = Buffer.from(body.content, 'base64').toString();
  console.log(decodedContent);
})().catch(err => {
  console.log(err);
});

.envにはTOKENを定義しておきます。

TOKEN=xxx

日本語ファイルを取得

ファイルというか URL の日本語部分はパーセントエンコーディングします。テスト.csvを取得したいならこんな感じです。

`https://api.github.com/repos/geekcojp/directory-maps/contents/${encodeURIComponent(
  'テスト'
)}.csv`;

過去の状態のファイルを取得

URLの後ろにref={COMMIT_HASH || BRANCH || TAG}なParamをつけます。

`https://api.github.com/repos/geekcojp/directory-maps/contents/${encodeURIComponent(
  'テスト'
)}.csv?ref=fdbb18abe52965420c9c96b9502ddf14ba28dd7d`;

Github から Personal Access Token の取得

Settings -> 'Developer settings' -> 'Personal access tokens' から 'repository' にチェックを入れて生成

こういうやつ。

# get-caller-file@2.0.1: The engine "node" is incompatible with this module. Expected version "6.* || 8.* || >= 10.*". Got "9.11.2"
# get-caller-file@2.0.1: The engine "node" is incompatible with this module. Expected version "6.* || 8.* || >= 10.*". Got "9.11.2" error Found incompatible module

Yarn を使っているなら --ignore-engines を付けると、ローカルのNodeJSのバージョンによってエラーになることを回避できます。

yarn --ignore-engines

スキーマ

スキーマ情報はwww.sitemaps.org/protocol.htmlに書かれいます。手書きでxmlを書くのは面倒くさいのでnodejsスクリプトで生成する感じにしてみる。

2つのパッケージをインストール

以下の2つをインストールします。

yarn add xml prettify-xml

xmlは木構造なオブジェクトをxmlにフォーマットしてくれて、prettify-xmlはxmlの整形パッケージです。

サンプルコード

簡単に書いてみました。

const fs = require('fs');
const path = requrie('path');
const xml = require('xml');
const prettifyXml = require('prettify-xml');

const tree = {
  urlset: [
    {_attr: {xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9'}},
  ]
};

tree.urlset.push({
  url: [
    {loc: 'そのページのURL',
    {lastmod: 'いつ変更したか'},
    {changefreq: '更新頻度'},
    {priority: '優先度 0~1 例えば 0.5'},
  ]
})
// ...他すべてのページを`push`
 
const sitemap = prettifyXml(xml(tree, {declaration: true}));
fs.writeFileSync(path.join(__dirname, '相対パス/sitemap.xml'), sitemap);

tree.urlset.push周りは色々リファクタして手間が少なくするようにするといいですね。
ちなみにchangefreqは以下から適当なのを選びましょう。

  • always

  • hourly

  • daily

  • weekly

  • monthly

  • yearly

  • never

lastmodchangefreqなどはは特に必須情報ではないようです。

node -e "console.log('#' + crypto.randomBytes(3).toString('hex'))"
# #1f514c

ランダム色をさくっと取得してcolorhexa.comで見る

xargsと組み合わせればcolorhexa.comで詳細を見れるようにもできます。その場合色値の前の#はいらないので少し注意です。

node -e "console.log(crypto.randomBytes(3).toString('hex'))" | xargs -I@ open https://www.colorhexa.com/@

僕が見たものだとこんなのや

error get-caller-file@2.0.1: The engine "node" is incompatible with this module.
Expected version "6.* || 8.* || >= 10.*".Got "9.11.2"

こんなのです。

error upath@1.0.4: The engine "node" is incompatible with this module.
Expected version ">=4 <=9". Got "10.15.1"

追加(2019-07-03)

sane@4.1.0: The engine "node" is incompatible with this module. Expected version

これは一応yarn--ignore-enginesというオプションをつければ回避できます。

yarn --ignore-engines

以下のようなファイル構造だとします。

.
├── ba
│   └── z.mdx
├── bar
│   └── b.mdx
├── baz
│   └── c.mdx
└── foo
    └── a.mdx

3 directories, 3 files

0か複数

*を使うと0か複数を表せます。

glob('ba*/**/*.mdx', (_, files) => {
  console.log(files);
});

これは[ 'ba/z.mdx', 'bar/b.mdx', 'baz/c.mdx' ]を得ます。*の部分は無いものでもマッチするのでbaも含まれます。

1か複数

?を使うと1か複数を表せます。

glob('ba?/**/*.mdx', (_, files) => {
  console.log(files);
});

これは[ 'bar/b.mdx', 'baz/c.mdx' ]を得ます。?は必ず何かしらの文字列がある必要があるので今度はbaは含まれません。

範囲

[]で囲むと範囲という意味になります。例えば[a-z]a,b,c,d,...みたいな意味になります。

glob('qqqq/ba[a-z]/**/*.mdx', (_, files) => {
  console.log(files);
});

よってこれも[ 'bar/b.mdx', 'baz/c.mdx' ]を得ます。

完全マッチの複数

@(foo|b?r)と書くとfoob?rの時にマッチします。中で?*など使えるので柔軟に複数指定できます。

glob('qqqq/@(foo|bar)/**/*.mdx', (_, files) => {
  console.log(files);
});

これは[ 'foo/a.mdx', 'bar/b.mdx' ]を得ます。

複数マッチの否定

!(foo|bar)と書くとfoobarじゃないものにマッチします。

glob('qqqq/!(foo|bar)/**/*.mdx', (_, files) => {
  console.log(files);
});

これは[ 'qqqq/baz/c.mdx' ]を得ます。

何でもいいディレクトリ

**を使うとディレクトリの名前・どこにあるかに関係なくマッチするようにできます。

glob('**/*.mdx', (_, files) => {
  console.log(files);
});

これは[ 'foo/a.mdx', 'bar/b.mdx', 'baz/c.mdx' ]を得ます。これはhoge/fuga/piyo/a.mdxというようなファイルであってもマッチします。

Encode

Buffer で読み込んでからtoStringbase64に変換します。

Buffer.from('foo').toString('base64');
// 'Zm9v'

Buffer で読み込めれば何でも。

class Foo {
  [Symbol.toPrimitive]() {
    return 'foo';
  }
}

Buffer.from(new Foo()).toString('base64');
// 'Zm9v'

Decode

encodebase64として Buffer で読み込み、文字列化します。

Buffer.from('Zm9v', 'base64').toString();
// 'foo'

JavaScript で飯食べたい歴約 9 年、 純( nju33 ) によるノートサイトです。

このサイトではドリンク代や奨学金返済の為、広告などを貼らせて頂いてますがご了承ください。

Change Log