20200707のNode.jsに関する記事は7件です。

SendGridでいい感じにメールの配信停止グループを管理する

個人で開発しているサービスにメールの配信基盤を整えようと思って色々調べていたので、その結果わかったことを備忘録としてまとめておきます。

メールの配信停止設定で最低限やっておきたいこと

メールの配信設定を行うにあたって、以下の項目が守られていることが個人的に望ましかったです。

  1. 簡単にメールを配信停止できること
  2. 自分のサービスとメール配信サービスでメールの配信停止設定を共有できること

1. 簡単にメールを配信停止できること

まず、送られるメールは簡単に配信停止できるようにすべきです。配信停止のベストプラクティスと、SendGrid の便利な機能にも以下のように書かれています。

  1. 簡単に配信停止できるようにする

配信停止の手順が簡単であればあるほど、受信者と送信者、双方にとってメリットがあります。配信停止のボタンやリンクをどこに置くか決める時、隠すように配置してはいけません。また、リンクがきちんと機能するか複数回チェックしましょう。リンクをフッタに配置するケースをよく見かけますが、どこに配置したとしても、見つけやすくわかりやすくする必要があります。

サービス運営側としては宣伝のためメールを送りたいと思うので、できればメールの配信を続けたいかと思いますが、そのあまり配信停止の設定が不便だとユーザーからの信用を損ないますし、UX も悪いです。

2. 自分のサービスとメール配信サービスでメールの配信停止設定を共有できること

SendGrid にて、メールの配信停止を行う手順は メールの種類ごとに配信停止を管理する - ドキュメント | SendGrid にもあるように、わりと簡単に行えそうでした。

しかし、実際にメールの配信設定を管理する際は、自分で作っているサービス側でもメールの配信設定ができる必要があります。

例えば、SendGrid 側でメールの配信を停止した場合、自分で作っているサービス側のメール配信設定もオフになっているべきです。この実装をどのようにすればよいか、あまりメール配信に慣れていない自分は調べるのに苦労しました。

メールの配信停止設定を管理する方法

いろいろ試した結果、SendGrid の Suppressions の API を利用すると、やりたいことが実現できそうでした。

SendGrid ではメールの配信停止グループを設定できるのですが、こちらの API を使うことで特定のメールアドレスと配信停止グループに対して

  • メールの配信設定の取得
  • メールの配信停止
  • メールの配信停止の取り消し

ができます。

あとは、自分のサービス上でこの API を呼び出してあげれば良いです。自分は Node.js を使っていたので、sendgrid/sendgrid-nodejsでのコードを参考までに載せておきます。

メールの配信設定の取得
import client from "@sendgrid/client";
import RequestOptions from "@sendgrid/helpers/classes/request";

client.setApiKey("SG.xxxxx.yyyyy");
(async () => {
  const request = {} as RequestOptions;
  const email = "example@gmail.com";
  request.method = "GET";
  request.url = `/v3/asm/suppressions/${email}`;
  const [response] = await client.request(request);
  console.log(response.body);
})();
メールの配信停止
import client from "@sendgrid/client";
import RequestOptions from "@sendgrid/helpers/classes/request";

client.setApiKey("SG.xxxxx.yyyyy");
(async () => {
  const request = {} as RequestOptions;
  const email = "example@gmail.com";
  const groupId = 12345;
  const data = {
    recipient_emails: [email]
  };
  request.body = data;
  request.method = "POST";
  request.url = `/v3/asm/groups/${groupId}/suppressions`;
  const [response] = await client.request(request);
  console.log(response.body);
})();
メールの配信停止の取り消し
import client from "@sendgrid/client";
import RequestOptions from "@sendgrid/helpers/classes/request";

client.setApiKey("SG.xxxxx.yyyyy");
(async () => {
  const request = {} as RequestOptions;
  const email = "example@gmail.com";
  const groupId = 12345;
  request.method = "DELETE";
  request.url = `/v3/asm/groups/${groupId}/suppressions/${email}`;
  const [response] = await client.request(request);
  console.log(response.body);
})();

ちなみに、余談ですがメールの送信も以下のような感じでできます。

import sendgrid from "@sendgrid/mail";

sendgrid.setApiKey("SG.xxxxx.yyyyy");

const msg = {
  to: "example@gmail.com",
  from: "no-reply@example.com",
  subject: "Sending with Twilio SendGrid is Fun",
  html: `
    <html>
        <body>
            ここが本文です<br />
            <a href="<%asm_preferences_raw_url%>">配信停止を管理する</a><br />
        </body>
    </html>`,
  asm: { groupId: 12345 }
};
(async () => {
  try {
    await sendgrid.send(msg);
  } catch (error) {
    console.error(error);

    if (error.response) {
      console.error(error.response.body);
    }
  }
})();

これにより、自分のサービスの設定画面からメールの受信・停止設定を行うことができますし、送信したメールの「メール配信停止」リンクからメールの配信を停止した際も、自分のサービス側で設定を同期できます。

おわりに

今回は SendGrid を利用しましたが、似たような API があるサービスであれば今回実現したかったことは実装できるかと思います。

ただ自分はあまりこの手のサービスを知らないので、もしおすすめのサービスをご存じの方がいらっしゃれば、ぜひコメント欄にて教えていただけますと嬉しいです!?


というわけで、この記事で書いた内容をもとにメールの配信機能を実装してみました!

メール通知機能を追加しました!|AnyMake|note

もしよろしければ、AnyMake もチェックしてみてください?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SiriっぽいTeamsアプリを作ってみる

はじめに

仕事にしても何にしても使えるものは使っておくに限る。
最近はリモートワークの影響でteamsを使い始めたので、これも使っておきたい。
どうせなら勤怠とかの自動化に使おうとも思ったが、敷居が高そうなので途中から計画変更してSiriにした。
だって、Siriっぽいもの作った事ありますって言っておけば何かしら仕事もらえるんじゃなかろうか。

結果

image.png
何も分からない俺のSiri

Teams API

TeamsにはTeamsに蓄えられた情報を扱うためのRest APIが用意されている。

これらのRestAPIを使ってタブやボットなどのアプリを作成する。
尚、APIで使用可能なリソースは下記種類がある。

リソース メソッド
team 各自のチームの一覧表示、すべてのチームの一覧表示、作成、読み取り、更新、削除、複製、アーカイブ、アーカイブ解除
group メンバーの追加、 メンバーの削除、所有者の追加、 所有者の削除、ファイルの取得、ノートブックの取得、プランの取得、予定表の取得
channel 一覧表示、作成、読み取り、更新、削除
teamsTab 一覧表示、作成、読み取り、更新、削除
teamsApp 一覧表示、公開、更新、削除
teamsAppInstallation 一覧表示、インストール、アップグレード、削除
chatMessage 送信
call 応答、拒否、リダイレクト、ミュート、ミュート解除、画面共有ロールの変更、参加者の一覧表示、参加者の招待
schedule 作成または置換、取得、共有
schedulingGroup 作成、一覧表示、取得、置換、削除
shift 作成、一覧表示、取得、置換、削除
timeOff 作成、一覧表示、取得、置換、削除
timeOffReason 作成、一覧表示、取得、置換、削除

2020-06-27現在では.NET, JS, Pythonでサンプルが用意されている。

参考になるサンプルを探す

サンプルを眺めていると、nodejs配下に50.teams-messaging-extensions-searchなるジャストなものがある。
このサンプルはなにをするものかと言うと、アプリケーションコマンドにnodeのパッケージ名を入力すると詳細を教えてくれる。と言うもの。
アプリケーションコマンドが何かと言うと、

image.png
ココ

これを元にsiriを作っていきたい。まずはREADMEに沿って環境を整える。

必要なパッケージを入れる。

nodejsのサンプルなので、必要なのはnodejs。特にバージョンの指定がないのでstableで良いと思う。
自分の端末にはもともと入っていたので特に変えてない。

image.png

nodejs入れたらinstall

npm install

ngrokの導入

READMEを読むとngrokを利用するらしいので、早速本家から落としてインストールする。尚ngrokに関しては有志の強い方が記事を書いてくださっているので、そちらを参照してほしい。
この記事でngrokに関する有用な情報はない。だって今回初めて触った。

インストール方法はngrokに登録してソフトをダウンロードして展開するだけ。
展開したらexeが出てくるのでパス通す。特に困る事はないハズ。

公式サイトの指示通りngrokをアカウントに接続させたら完了。

image.png
とりあえずヘルプ出してみた

あとは実行するだけ

ngrok http -host-header=rewrite 3978

Azureの準備

teamsを使う以上、Azureを使う。で、Azureの準備。

Bot Framework registration resourceの手順通りに進める。
Azure Portalを開き、リソースを作成する。

image.png

botと打つとBot Channel Registrationの候補が現れるのでこれを選ぶ。(公式手順ではWeb App Botでもできるらしい)

image.png

一礼して作成

image.png

下記設定で作成ボタンをクリック。するとデプロイまで進んでくれる。Azure賢い。

項目 設定値
ボットハンドル miyatama-worksheet-hater
サブスクリプション 従量課金(デフォルト)
リソース miyatama-teams-learning(新規作成)
場所 米国西部(かっこいいから)
価格レベル S1
メッセージングエンドポイント
ApplicationInsight オン
ApplicationInsightの場所 East US
MicrosoftアプリIDとパスワード 自動生成

で、しばらく放っておくと完了の通知が来る。

image.png
や っ た ぜ

すべてのリソースを開くと2つリソースが追加されている(botとApplication Insight)。Botの方をクリック。

image.png

image.png

設定をクリック

image.png

右側ペインを下にスクロースるとMicrosoft App IDの項目があるので、管理のリンクをクリック

image.png

新しいクライアントシークレットをクリック

image.png

説明を入力して追加をクリック

image.png

ちゃんと追加される。この時にキーをコピーしてファイルに保存しておく。大事な事なのでもう一回書いておく。
シークレットをコピーしてファイルに保存しておく

image.png
ちゃんと追加出来ててえらい。

Azureでteams使える様にする。

Azure Portalで発行したAppIDとパスワードを.envファイルに追記する。

項目 設定値
MicrosoftAppId 後述
MicrosoftAppPassword 前述のシークレット発行時にコピーした文字列 

AppIDはbotの設定に記載されている

image.png

これで準備ができたので早速動かす。

npm start

teams用の設定を行う

teamsAppManifest/manifest.jsonを編集する。

  • idへMicrosoft App IDを設定
  • composeExtensions.botIdへMicrosoft App IDを設定

その後、teamsAppManifest内のファイルをZipに固める(ファイル名はmanifest.zip)。
大事な事なのでもう一度書こう。
teamsAppManifest内のファイルをZipに固める

image.png

teamsからカスタムアプリのアップロードを行う。アプリのアイコンをクリックし、ペインをスクロールするとカスタムアプリをアップロードの項目が出てくるのでクリック。

image.png

アップロードで先ほど作成したzipファイルを選択する。成功した場合はアプリが画面上に表示される。

image.png
アイコン変だけど気にしない

アプリをクリックして追加を行う

image.png

早速よびだす

image.png
だめでした。

これはなぜかと言うと下記図で言う所のAzureとngrokが連携できていないから。

flow.png

と言うわけでngrokで用意したendpointをAzureに教えてあげないといけない。
まずはココを参考にchannelを作成する。
次に、ngrokeのendpointをAzureに教える。ngrokのendpointはngrok http -host-header-rewrite 3978で実行した時の結果を参照してほしい。
万が一gitbashで実行してしまった場合はwinptyを使うなりコマンドプロンプトで実行するなりなんなりで対処してほしい。

image.png
上記例だとhttps://0a3496160a1a.ngrok.io/api/messages

Azure PortalからBotのリソースを開き、設定を表示する。すると、メッセージングのエンドポイントなる項目があるので、ここにngrokのendpointを張り付ける。

image.png

もう一回試す

image.png
や っ た ぜ

Siriっぽくする

サンプル実行できただけでもかなりお腹いっぱいなのだが、元来の目的であるSiriの作成に入る。
Siriと言えば、すみません。よくわかりません。だ。異論もあるだろうか、私のイメージではそうだ。

botのコードを見てもらうと分かる通り、検索した結果を返すだけだ。これをSiri化するのは簡単だ。
固定ですみません。よくわかりません。を返せばよいだけだ。

中の仕様がよく分からない方はここを見てほしい。めちゃくちゃ親切に書いてある。
書き変えた(?)後のコードは以下の通り。

const axios = require('axios');
const { TeamsActivityHandler, CardFactory } = require('botbuilder');

class TeamsMessagingExtensionsSearchBot extends TeamsActivityHandler {
    async handleTeamsMessagingExtensionQuery(context, query) {
        const attachments = [];
        const heroCard = CardFactory.heroCard("result");
        const preview = CardFactory.heroCard("すみません。よくわかりませんでした。");
        const attachment = { ...heroCard, preview };
        attachments.push(attachment);

        return {
            composeExtension: {
                type: 'result',
                attachmentLayout: 'list',
                attachments: attachments
            }
        };
    }
}

module.exports.TeamsMessagingExtensionsSearchBot = TeamsMessagingExtensionsSearchBot;

早速試す

image.png
や っ た ぜ

ふりかえり

冒頭にも記載した通り、最初は勤怠の自動化をやろうかと思って色んなサンプルを眺めたりしていた。
が、途中でめんどくさくなって、何でもいいからアウトプットしておく運びとなった。
まぁ、ここまでやっておけば後は自然言語処理でも賢さ演出するぐらい誰でもできるし、何とかなるだろう。
teamsの記事を何個か書く予定なので無駄にはならないハズだ。

何よりも、勉強の方法を議論する位なら勉強した方が早い。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

typescriptから直接bundle.jsを作成する方法

本記事ではtypescriptから直接bundle.jsを作成する方法について書いていきます。

<今までのbundle.jsの作成方法>
1.tsファイルをコンパイルしてjsファイルを作成
2.jsファイルをbundleしbundle.jsを作成

この流れが面倒なので直接やってしまおう。

1.ts-loaderをインストールする

npm install --save-dev ts-loader typescript

2.webpackの設定ファイルに記述

webpack.config.jsにどのファイルにts-loaderを実行するかを記述する。

webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/main.ts',  //最初に読み込ませるファイルもtsファイルに変更

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devtool: 'inline-source-map',

  module: {
    rules: [{
      test: /\.ts$/,  //どういうファイルに対して
      use: 'ts-loader',  //何をするか
      exclude: /node_modules/   //このファイルは例外
    }]
  }
}

3.buildしてみる

1.以下のコマンド実行。
npm run build

あれ、エラーだけど、、、、
ERROR in ./src/main.ts
Module not found: Error: Can't resolve './foods.js' in '/Users/*****/*****/******/src'
@ ./src/main.ts 1:0-35 2:0-5

ここでのエラーで原因は、main.tsの中でjsファイルをインポートしようとしているため。

main.ts
import { Foods } from "./foods.js";

Foods.getInstance();

そしたらfoods.tsに書き換えればいいんじゃない?
スクリーンショット 2020-07-07 15.23.58.png

それでもエラーが出てしまいます。

しかし、Webpackを使用する場合は拡張子は.tsで正解なんです!

でもエラーが出ているままって気持ち悪いですよね。。。

こうすることで解決できます!

1.importもとの拡張子を消しちゃいます。
スクリーンショット 2020-07-07 15.28.53.png
※このままだとbuild時にエラーになります

2.webpackの設定ファイルに以下を記述します。

webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/main.ts',

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devtool: 'inline-source-map',

  module: {
    rules: [{
      test: /\.ts$/,
      use: 'ts-loader',
      exclude: /node_modules/
    }]
  }
--------ここから--------------------
  resolve: {
    extensions: ['.ts','.js']
  }
}

これを書くことで拡張子がなくてもOK。

この記述でインポートしようとした時に拡張子がなかったら左から調べてくれるようになります。

Webpackって本当に便利ですね。。。

3.再度buildしてみる

以下のコマンド実行。
npm run build

今回は無事にエラーなくbundle.jsが作成されましたね!!!

以上になります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

typeScriptにWebpackを使用する

※あくまで個人の学習ノートなので参考程度に

1.package.jsonを追加

npm init -y

package.jsonが作成される

2.webpackインストール

npm install --save-dev webpack webpack-cli

node_moduleのフォルダとpackage-lock.jsonが作成される。

※作成されるnode_moduleはgitにpushしない

3.webpack.config.jsをディレクトリに追加

webpack.config.jsはwebpackの設定ファイル

webpack.config.js
const path = require('path'); //requireimportと同じ扱いでpathnodejsがもっているモジュール

module.exports = {
  entry: './dist/main.js', //一番最初に読み込ませるjsファイル

  output: {    //生成したファイルをどこに格納するかを指定
    filename: 'bundle.js', //生成されるファイル名
    path: path.resolve(__dirname, dist), //生成されるファイルの格納ディレクトリ
  }
}

4.bundle.jsを作成

npm run build

bundle.jsが作成される。

5.HTMLファイルの記述変更

jsファイルの読み込み先を先ほど作成したbundle.jsに変更
(bundle.jsに全てのjsファイルのコードがまとまっているため)

index.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
  <script src="dist/bundle.js" defer></script>
</head>

以上で終了。

-----------ここからはやってもやらなくても良い-------------

・sourceマップにjsファイルを表示したい場合

1.現在の状態だと以下のように検証ツール上にはbundle.jsしか表示されていない。
スクリーンショット 2020-07-07 14.32.57.png

2.webpackの設定ファイルにdevtool: 'inline-source-map'と追加する

webpack.config.js
const path = require('path');

module.exports = {
  entry: './dist/main.js',

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, dist),
  },
  devtool: 'inline-source-map'  //この行を追加
}

3.再度buildすると以下のように変わる
スクリーンショット 2020-07-07 14.39.24.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【アプリ編】textlintではじめる自動文章校正

textlintとは

textlint(テキストリント)は、設定した校正ルールに基づいたミスの指摘・修正を自動化するツールです。

本来はコマンドプロンプト等の『黒い画面』からインストールして使うのですが、作者の方(@azu_reさん)がより使いやすいデスクトップアプリ版をリリースしてくださっています。
こちらで十分な方にとっては圧倒的におすすめです。

アプリのダウンロード

https://github.com/textlint/textlint-app/releases/tag/v1.4.1

↑こちらのページからインストーラをダウンロード、実行します。

アプリを開くとこのような画面が出ます。▼
スクリーンショット 2020-07-07 11.47.51.png

基本的にはメモ帳やテキストエディットのような「エディタアプリ」と同じだということがわかと思います。

しかしこのアプリを使うためには、以下の2点を用意する必要があります。

・ワーキングディレクトリ(作業用フォルダ)
・校正ルールプリセット

順番に説明します。

ワーキングディレクトリの設定

”ディレクトリ”というのは、つまりフォルダのことです。
筆者も最初わからなかったんですが、プログラミングの工程でコマンド操作をする際には、フォルダのことをディレクトリと呼ぶみたいです。

textlintを使う上では、どこのディレクトリで校正作業するのか?という設定が必要になります。

その設定をするのは、左カラムの『Settings』画面。▼
スクリーンショット 2020-07-07 11.48.02.png

上の方にあるWorking directoryの部分に、作業するフォルダのパスを入力します。
何も設定をしないとデフォルトでtextlint-appのフォルダが使われますが、実際に使う際にはデスクトップ等の見やすい場所に置いておく方が何かとスムーズかと思います。お好みでフォルダをご用意ください。
スクリーンショット 2020-07-07 12.00.18.png
↑今回はこのフォルダを使います。

作業用のフォルダを決めたら『.textlintrc』というファイルを用意します。
『.』から始まるこのファイルは”隠しファイル”といって、フォルダを開いても表示されません。

ファイルを作る時はエディタを使いましょう。
サクラエディタやAtomで空のファイルを作成し、名前をつけてフォルダへ保存します。
スクリーンショット 2020-07-07 12.24.42.png
(Macの場合「command」 + 「shift」 + 「.」でこのように隠しファイルを表示できます)

ファイルを用意できたら、同じフォルダ内に『rule』というフォルダを作ります。
スクリーンショット 2020-07-07 12.34.49.png

ここまでできたら、次はルールの設定をしていきます。

校正ルールの設定

現状では、textlintは何の校正ルールも持っていません。
実際に校正を行うには、ルールを自分で設定するか、誰かの作ったルールプリセットをインストールする必要があります。

今回やりたいのは『表記揺れを統一させること』(『是非』は『ぜひ』の表記に統一したいなど)なので、textlint-rule-prhというプリセットを使ってみます。

prhを使うためには、間違い表現と正しい表現をまとめたymlファイルが必要です。
エディタで『jisho』フォルダを開いて、『rule』フォルダ内にファイルを作成しましょう。
スクリーンショット 2020-07-07 12.44.52.png
今回は『jisho.yml』というファイル名にしました。
(画像で使っているVSCodeでは、ymlファイルを開くと紫の!マークがつきます。特にエラーではないのでご心配なく)

ymlファイルにルールを記述する

https://github.com/textlint-rule/textlint-rule-prh
▲こちらのページに詳しい記述方法が書いてありますが、基本的にはこんな感じです。

jisho.yml
version: 1

rules:
  - expected: 正しい表現です。
    pattern: 間違った表現です。

  - expected: 正しい書き方。
    patterns:
      - こんなパターン
      - どんなパターン
      - あんなパターン

このように『patternに該当する表記があったらexpectedが正しいですよ』という指示を書きます。
「是非」→「ぜひ」のような統一の場合はこの書き方。

もし書き間違いなど、正解パターンに対して間違いパターンをいくつも指定したいときは、下にあるようにpatternsと書いたあと間違いパターンを書き連ねていきます。

.textlintrcの中身を書く

最初に作った隠しファイルは、使うルールを指定するための設定ファイルです。
その中にymlファイルのパスを引いて、「これを使います」と指示しましょう。

{
  "rules": {
    "prh": {
      "rulePaths": ["rule/jisho.yml"]
    }
  }
}

(コピペでOKです)

アプリ側での設定

ここまで、作業用フォルダとその中身を用意しました。

jisho
 └ rule - jisho.yml
 └ .textlintrc

このようなファイル構成になっているかと思います。
このjishoフォルダを、textlintアプリで開いてみます。
スクリーンショット 2020-07-07 13.13.58.png
Working directoryの入力欄に、jishoフォルダのパスを書きます。
Windowsだと、フォルダを開けば上の方にパスが表示されるので、それをコピーして貼り付ければOKです。
スクリーンショット 2020-07-07 13.16.35.png
パスを書いてLoadを押すと、中に入っている.textlintrcの中身が下に出てきます。この状態で下の方にあるinstallsaveを押しましょう。

すると、アプリに内蔵されているnpmによってプリセットがインストールされ、アプリでprhが使えるようになります。

試しにエディタに戻って、間違い表現を入力してみましょう。
(最初に書いてあるガイド文は消して大丈夫です)
スクリーンショット 2020-07-07 13.28.51.png
右のカラムに『正規表現はこっちですよ?』という指摘が出ました。
間違いの数だけこの指摘が表示されます。

Fix all errorsと書かれた白いところを押せば、一括で正しい方に修正されます。
スクリーンショット 2020-07-07 13.29.02.png
何個あってもワンクリックです。とても便利!
ただ逆にいうと一括での修正しかできないので、「ここだけは例外的に直さない」という使い方はできません。
日本語的に変な箇所がないかどうか注意しましょう。

(アプリ版ではなくCLIで導入してVSCode上で使う場合なら、そういう融通も利かせられます。環境構築が難しいですがよろしければそちらも挑戦してみてください。)

その他のルール

prhは表記揺れを直すだけですが、他のルールを使えば

・一文で「、」は4つまで
・「かもしれない」などの弱い表現は禁止する

などの校正ルールを追加することもできます!

ルールの自作・カスタマイズができるのもtextlintの魅力ですが、そちらはプログラミング初学者にはけっこうハードルが高いようなので、筆者はまだチャレンジしていません。
おもしろそうなのでJavaScriptに慣れてきたらいずれ…

他にもいろんな方のルールがGitHub上で公開されているので、是非探してみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

browser-syncのport番号をランダムにする

複数の案件を同時に進めている都合上、複数個のbrowser-syncを同時に走らせたいときportが衝突してイライラしちゃうので、そもそもportをランダムにしとけばいいんじゃないか説。

他にいい方法があれば教えてください。。。

// browser-sync.js
module.exports = () => {
    const path = require('path');
    const browser = require('browser-sync').create();

    browser.init({
        files: [
          // 監視したいファイルのパターンリスト
        ],
        // 動的・プライベート ポート番号からランダムで
        port: Math.floor(Math.random() * (65535 - 49152)) + 49152,
        startPath: '/',
        server: {
            baseDir: path.join(__dirname, 'public')
        }
    });
};

// 呼び出し側のjs
require('./browser-sync')();

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MAC:node.jsでmysqlへ接続する

node.js から mysqlに接続するのに苦労しましたので覚書をします。

環境

macOS : 10.15.5 (Catalina)
node.js : v14.3.0
mysql : ver 8.0.19

mysqlインストール

shell
$ brew install mysql

でインストールされました。
(他の情報でmpnを使用するやり方が書いてありましたが、私の環境では起動ができませんでした)

コネクションを実行するコード

mysqlconnection.js
//------------------------------------------------------------
//      my sql connection
//------------------------------------------------------------
var mysql = require('mysql');

//DBの定義
var dbConfig = {
  host     : 'localhost', //接続先ホスト
  user     : 'root',      //ユーザー名
  password : '******',    //パスワード
  database : '******'     //DB名
};

var connection;

function handleDisconnect() {
    console.log('create mysql connection');
    connection = mysql.createConnection(dbConfig); //接続する準備

    //接続
    connection.connect(function(err) {
        if(err) {
            console.log('error when connecting to db:', err);
            setTimeout(handleDisconnect, 2000); //2秒待ってから処理
        }
    });

    //error時の処理
    connection.on('error', function(err) {
        console.log('db error', err);
        if(err.code === 'PROTOCOL_CONNECTION_LOST') {
            handleDisconnect();
        } else {
            throw err;
        }
    });

    module.exports = connection; //connectionを(他のファイルから)requireで呼び出せるようにする
}

handleDisconnect();

実行するにはシェル(ターミナル)に以下を入力します

shell
   $ node mysqlconnection.js

エラー発生

私の環境では上記を実行してもエラーが出ました。

  1. mysqlが起動していない場合のエラー
 errno: -61,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 3306,
  fatal: true

このエラーの対処は

shell
  $ mysql.server start

とします。

2.認証方法エラー
新しいmysqlで認証方法が変更になっていてnode.jsからは古い認証方法でアクセスするためにそれに合わせる必要があるようです。

ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client

この対処は以下を参照しました。

Node.jsでMySQL 8.0へ接続しようとする時に発生するエラー

ですがこれをこのままやってもうまくいかず

mysqlの初期パスワードをクリアする必要がありました。
他のサイトではvar/log/mysqld.log に初期パスワードが残っているとの情報があったのですが、私の環境ではありませんでした。
それで以下の記事

Mac ローカル環境の MySQL 8.0 のrootパスワードを忘れた時のリセット方法

を参考にて、
1.サーバーを停止
$ mysql.server stop
2.MySQLをセーフモードで起動する。
$ mysqld_safe --skip-grant-tables &
3.rootユーザのパスワード無し状態でログインする。(同じターミナルで大丈夫でした)
$ mysql -u root
4.rootユーザーのパスワードを空に設定する。
mysql> UPDATE mysql.user SET authentication_string=null WHERE User='root';
5.セーフモードで開いたMySQLを閉じる
mysql> exit
6.セーフモードで動作しているMySQLをkillする。
$ mysql.server status
SUCCESS! MySQL running (XXXXX)
$ kill XXXXX

7.通常モードでMySQLを起動する。
$ mysql.server restart
8.rootでmysqlを起動する。(パスワード要求されるがENTERをおす。)
$ mysql -u root -p
9.パスワードを再設定する。
mysql> USE mysql;
10.ここで先ほどの
Mac ローカル環境の MySQL 8.0 のrootパスワードを忘れた時のリセット方法
に書いてあるSQLを実行します

mysql > ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'

passwordの部分はrootでログインを行う際の任意のパスワードです。

ここまで実行するとこのエラーはなくなります。

その他注意

・node.jsからmysqlへアクセスするにはmysqlにdbを作成する必要があります。

mysql
 mysql>create db _test

・mysqlconnection.jsは作成したdbと、設定パスワードを記述する必要があります

mysqlconnection.js
var dbConfig = {
  host     : 'localhost', //接続先ホスト
  user     : 'root',      //ユーザー名
  password : '******',    //パスワード
  database : '******'     //DB名
};
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む