- 投稿日:2020-05-27T22:09:49+09:00
プログラミング素人のIoTサービス開発 -ログイン認証-
はじめに
2020年3月からプログラミングの勉強を始めて、7月までにWebサービス制作に挑戦しているプログラミング素人の制作記録です。
自分の技術レベル
・ProgateでHTML/CSS、JavaScript、Node.JSを受けた
・Expressフレームワークでget通信とpost通信を扱えるようになってきた
・JSのPromeseの概念が少しだけ理解できてきた
・obnizを触ったことがある
https://note.com/hiromae/n/n4850983a3f92目標制作物&必要な技術ロードマップ
熱くなる季節に向けて、熱中症予防のための温度検知サービスの制作に取り組んでいます。
身近な問題をIoTで解決できないか考えてみた
https://note.com/hiromae/n/n0e4a88bb501c■現在構想しているサービス像
制作のために今後身につける必要がある技術が山ほどあります。
今回はサービスへのログイン認証サービスに触ってみました。
今回インプットしたもの
Firebase
https://firebase.google.com/?hl=ja今回のアウトプット
emailとpwをexpressのWebサーバに渡し、Firebaseで認証成功したらログイン後ページに遷移させることができました。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous" /> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous" ></script> <title>Document</title> </head> <body> <div class="container py-5"> <form method="POST" action="/login" id="app"> <div class="form-group"> <label for="email">Email address</label> <input type="email" class="form-control" id="email" aria-describedby="emailHelp" name="email" /> <small id="emailHelp" class="form-text text-muted" >We'll never share your email with anyone else.</small > </div> <div class="form-group"> <label for="password">Password</label> <input type="password" class="form-control" id="password" name="password" /> </div> <div class="form-group form-check"> <input type="checkbox" class="form-check-input" id="exampleCheck1" /> <label class="form-check-label" for="exampleCheck1" >Check me out</label > </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuelidate@0.7.4/dist/validators.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuelidate@0.7.4/dist/vuelidate.min.js"></script> <script> Vue.use(window.vuelidate.default); const { required, email } = window.validators; const app = new Vue({ el: "#app", data: { title: "入力フォームバリデーション", email: "", password: "", }, validations: { email: { required, }, }, methods: { submitForm() { console.log("submit"); }, }, }); </script> </html>const express = require("express"); const app = express(); //Firebaseモジュールの読み込み const firebase = require("firebase/app"); require("firebase/auth"); //Firebaseの初期化 var firebaseConfig = { apiKey: "", authDomain: "", databaseURL: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", measurementId: "", }; // Initialize Firebase firebase.initializeApp(firebaseConfig); app.use(express.static("public")); app.use(express.urlencoded({ extended: false })); app.get("/", (req, res) => { res.render("index.ejs"); }); //ログインボタン押したときの処理 app.post("/login", (req, res) => { console.log(req.body.email); console.log(req.body.password); // ログイン処理の定義 let handlerLogin = async function () { console.log("handlerLogin"); try { const resSignInWithEmailAndPassword = await firebase .auth() .signInWithEmailAndPassword(req.body.email, req.body.password); console.log("↓resSignInWithEmailAndPasswordをconsole.log↓"); console.log(resSignInWithEmailAndPassword.email); res.render("main.ejs"); } catch (error) { console.log(error); const errorCode = error.code; const errorMessage = error.message; if (errorCode === "auth/wrong-password") { console.log("Wrong password."); res.render("pwWrong.ejs"); } else { console.log(errorMessage); } } }; handlerLogin(); }); app.listen(process.env.PORT || 8080); console.log("server listen...");振り返り
・これで認証したって言えるのだろうか・・・?
・認証後は確かセッション情報を保有してそれによってログイン状態を保つとか聞いたことあるけど・・・
- 投稿日:2020-05-27T18:42:05+09:00
JavaScript thisの挙動の不思議
thisの挙動や関数スコープのことについて。
実行環境 node v14.2.0
thisの挙動(通常関数)
function hoge() { console.log(this); } function foo() { "use strict"; console.log(this); } hoge(); //globalオブジェクトが出力 foo(); //undefinedが出力ほぼほぼ同じ関数ですが結果が変わってきます。
hoge関数は、globalに紐付けせずに実行してもglobalオブジェクトを参照し出力します。デフォルトでglobalオブジェクトが紐付けされているということです。しかし、strictモードでは関数がどのオブジェクトにも紐付けされていなければ、この値は未定義になります。したがって、strictモードだとデフォルトでオブジェクトの紐付けは行われないということです。
thisの挙動(アロー関数)
console.log(this); //{} が出力 var hoge = () => { console.log(this); }; var bar = () => { "use strict"; console.log(this); }; hoge(); //{} が出力 bar(); //{} が出力ここでの結果は、globalオブジェクトを指すのではなく、関数実行時に内包している親の{}を示しています。
thisの挙動2(アロー関数)
global.name = "Taro"; let helloName = () => { console.log(`hello! ${this.name}`); }; let Hanako = { name: "Hanako", hello: helloName, }; helloName(); //hello! Hanako.hello(); //hello!@shiracamus様にご指摘、コメントいただいたため、整理、修正中。
nodeの場合は上記のように"hello!"しか表示されません。内包している{}が表示されています。しかし、ブラウザであれば"hello! Taro"と表示されます。つまり、globalオブジェクトのnameが呼び出されていることがわかります。
※ブラウザの場合は1行目のglobalをwindowに変更thisはいろいろな場合で値が変わるようでややこしいです。
また、thisの挙動からは少し逸れますがこんなこともやってみます。global.nameをvar宣言に変えてみます。
thisの挙動3(アロー関数)
var name = "Taro"; let helloName = () => { console.log(`hello! ${this.name}`); }; let Hanako = { name: "Hanako", hello: helloName, }; helloName(); //hello! Hanako.hello(); //hello!結果はブラウザ、node共に同じになります。
つまりvarもグローバル変数に値が格納されていることになります。では次に、if文の中で宣言してみます。
thisの挙動4(アロー関数)
if(true) { var name = 'Taro'; } let helloName = () => { console.log(`hello! ${this.name}`); }; let Hanako = { name: "Hanako", hello: helloName, }; helloName(); //hello! Hanako.hello(); //hello!nodeの場合は{}を示しているので何も表示されません。
しかし、ブラウザの場合は同じようにTaroが表示されます。if文の中で宣言してもglobal変数として宣言しているのでnameを使用することができます。次に、実行する場所によってthisの示す値が異なる挙動をみていきます。
こちらは関数の実行する場所が異なることによる挙動の違いが見れます。
Hanakoの場合はHanakoオブジェクトの中で関数を実行しているのでHanakoが出力されます。thisの挙動5(アロー関数)
var name="Taro" let displayName=function(){ console.log(this.name); } let hanako={ "name":"Hanako", "display":displayName } displayName(); // nodeではundefined、 ブラウザはTaroと表示 hanako.display(); //Hanakothisの値を制御してみます。
明示的にバインドしてthisが任意の物を指し示すようにします。thisの挙動6(アロー関数)
var name="Taro" let Hanako ={ "name":"Hanako", } let displayName=function(){ console.log(this.name); } displayName(); //Taro displayName.apply(Hanako); //Hanako displayName.call(Hanako); //Hanako let bindDisplayName= displayName.bind(Hanako); //Hanako bindDisplayName();thisの値を制御しました。
結果apply, call, bindDisplayNameで明示的にバインドしたものはHanakoを指し示すようになっています。
- 投稿日:2020-05-27T16:37:55+09:00
Javascriptで電話番号のバリデーションと変換(E.164)に便利なライブラリの紹介
今回したいこと
- 日本の電話番号(03-1234-5678)などを、E.164表記(+81312345678)に変換したい
- ついでにバリデーションも出来るといいかも
環境
- Node.js
ライブラリ
Googleが提供している電話番号をバリデーションと自動フォーマット可能なlibphonenumberのnpm版であるgoogle-libphonenumberを使用します。
google-libphonenumberの使用方法
インストール
npm install google-libphonenumber例1)'202-456-1414'を'US'のE164表記に変換
// Require `PhoneNumberFormat`. const PNF = require('google-libphonenumber').PhoneNumberFormat; // Get an instance of `PhoneNumberUtil`. const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance(); // Parse number with country code and keep raw input. const number = phoneUtil.parseAndKeepRawInput('202-456-1414', 'US'); // Format number in the E164 format. console.log(phoneUtil.format(number, PNF.E164)); // => +12024561414例2)全角・半角混合の日本の電話番号をE164表記に変換
// Require `PhoneNumberFormat`. const PNF = require('google-libphonenumber').PhoneNumberFormat; // Get an instance of `PhoneNumberUtil`. const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance(); const phoneNumbers = [ '03―1111―2222', '03 1111 2222', '(03)1111-2222', '0312345678', '03 1234 5678', '03-1234-5678', '(03)-1234-5678', '09012345678', '090-1234-5678', '09012345678', '090―1234―5678', '0120-123-123' ] const replacedNumbers = phoneNumbers.map(phoneNumber => { const replacedNumber = formatNumber(phoneNumber); return replacedNumber; }) function formatNumber(str){ const number = phoneUtil.parseAndKeepRawInput(str, 'JP'); return phoneUtil.format(number, PNF.E164); } console.log(replacedNumbers); // =>["+81311112222","+81311112222","+81311112222","+81312345678","+81312345678","+81312345678","+81312345678","+819012345678","+819012345678","+819012345678","+819012345678","+81120123123"]その他の使い方
READMEをそのままのっけています。
バリデーションも出来そうです。// Require `PhoneNumberFormat`. const PNF = require('google-libphonenumber').PhoneNumberFormat; // Get an instance of `PhoneNumberUtil`. const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance(); // Parse number with country code and keep raw input. const number = phoneUtil.parseAndKeepRawInput('202-456-1414', 'US'); // Print the phone's country code. console.log(number.getCountryCode()); // => 1 // Print the phone's national number. console.log(number.getNationalNumber()); // => 2024561414 // Print the phone's extension. console.log(number.getExtension()); // => // Print the phone's extension when compared to i18n.phonenumbers.CountryCodeSource. console.log(number.getCountryCodeSource()); // => FROM_DEFAULT_COUNTRY // Print the phone's italian leading zero. console.log(number.getItalianLeadingZero()); // => false // Print the phone's raw input. console.log(number.getRawInput()); // => 202-456-1414 // Result from isPossibleNumber(). console.log(phoneUtil.isPossibleNumber(number)); // => true // Result from isValidNumber(). console.log(phoneUtil.isValidNumber(number)); // => true // Result from isValidNumberForRegion(). console.log(phoneUtil.isValidNumberForRegion(number, 'US')); // => true // Result from getRegionCodeForNumber(). console.log(phoneUtil.getRegionCodeForNumber(number)); // => US // Result from getNumberType() when compared to i18n.phonenumbers.PhoneNumberType. console.log(phoneUtil.getNumberType(number)); // => FIXED_LINE_OR_MOBILE // Format number in the E164 format. console.log(phoneUtil.format(number, PNF.E164)); // => +12024561414 // Format number in the original format. console.log(phoneUtil.formatInOriginalFormat(number, 'US')); // => (202) 456-1414 // Format number in the national format. console.log(phoneUtil.format(number, PNF.NATIONAL)); // => (202) 456-1414 // Format number in the international format. console.log(phoneUtil.format(number, PNF.INTERNATIONAL)); // => +1 202-456-1414 // Format number in the out-of-country format from US. console.log(phoneUtil.formatOutOfCountryCallingNumber(number, 'US')); // => 1 (202) 456-1414 // Format number in the out-of-country format from CH. console.log(phoneUtil.formatOutOfCountryCallingNumber(number, 'CH')); // => 00 1 202-456-1414(おまけ)ライブラリを使わないでやってみた
最初はgoogle-libphonenumberを知らなかったので、正規表現でやってみました。
const phoneNumbers = [ '03―1111―2222', '03 1111 2222', '(03)1111-2222', '0312345678', '03 1234 5678', '03-1234-5678', '(03)-1234-5678', '09012345678', '090-1234-5678', '09012345678', '090―1234―5678', '0120-123-123' ] const replacedNumbers = phoneNumbers.map(phoneNumber => { const replacedNumber = toE164Number(phoneNumber); return replacedNumber; }) function toE164Number(strVal){ // 半角変換 const halfVal = strVal.replace(/[!-~]/g, function( tmpStr ) { // 文字コードをシフト return String.fromCharCode( tmpStr.charCodeAt(0) - 0xFEE0 ); } ); console.log("halfVal" ,halfVal); // 文字の変換 const number = phoneUtil.parseAndKeepRawInput(halfVal, 'JP'); console.log(number) console.log(phoneUtil.format(number, PNF.E164)); return halfVal.replace(/[\-\s+()-―]/gi, '').replace('0','+81'); }最後に
google-libphonenumberはかなり便利だなと思いました。
ただ電話番号を変換するときにJPなどの国コードを指定しないといけないので、素の電話番号形式から国コードを判定するものがあればいいんですけどね。。
- 投稿日:2020-05-27T12:11:51+09:00
PuppeteerのBrowserFetcherクラス
今回はPuppeteerのBrowserFetcherクラスについて書いていきたいと思います。
BrowserFetcherクラス
BrowserFetcherはChromiumとFirefoxの異なるバージョンをダウンロードして、管理することができます。
BrowserFetcherはChromiumのバージョンを("533271"にたいな)指定するrevision string上で操作します。revision stringはomahaproxy.appspot.comから得ることができます。と、言いたいところなのですが、確認したところ、存在しないものが多いので、こちらの方を見てください。
Firefoxの場合、BrowserFetcherはFirefox Nightlyをダウンロードして、("75"にたいな)バージョン番号を操作します。Firefox Nightlyのホストはこちらを見てください。
canDownloadメソッド
revisionが利用可能かどうかを確かめるメソッド。
ホストからダウンロード可能であれば、
true
を返してくれます。例(createBrowserFetcherの設定によって結果が変わります):
const puppeteer = require('puppeteer'); async function checkRevision(revision) { const browserFetcher = puppeteer.createBrowserFetcher(); const isAvailable = await browserFetcher.canDownload(revision); if(isAvailable) { console.info('This revision is available.'); } else { console.info('This revision isn\'t available.'); } } checkRevision('756066'); // win64 checkRevision('1000583'); // This may release from now on but this isn't release at the moment. checkRevision('78.0a1'); // If this product is Firefox, this result is true.結果:
This revision is available. This revision isn't available. This revision isn't available.downloadメソッド
ChromiumもしくはFirefox Nightlyをダウンロードするメソッド。
browserFetcher.download(revision[, progressCallback]) revision string ダウンロードするためのrevision progressCallback function(number, number) downloadedBytes number ダウンロードされたバイト数。 totalBytes number 合計ダウンロードバイト数。簡単な例:
const puppeteer = require('puppeteer'); (async () => { const browserFetcher = puppeteer.createBrowserFetcher(); await browserFetcher.download('771731', (downloadedBytes, totalBytes) => { // any code... }); })();hostメソッド
使用されているダウンロードホストを返すメソッドです。
localRevisionsメソッド
ディスク上でローカルに利用可能な(現在の
product
の)すべてのrevisionのリストを返すメソッド。platformメソッド
mac
、linux
、win32
、またはwin64
のいずれかを返すメソッド。productメソッド
chrome
もしくはfirefox
のいずれかを返すメソッド。removeメソッド
ダウンロードされたChromiumもしくはfiredfoxをrevisionを指定して削除するメソッド。
revisionInfoメソッド
revisionを指定してそのrevisionの情報を出すメソッド。
サンプル
ローカルにはrevision:389298と771731がダウンロード済み。
const puppeteer = require('puppeteer'); (async () => { const browserFetcher = puppeteer.createBrowserFetcher(); console.info('host: ' + await browserFetcher.host()); await (browserFetcher.localRevisions()).then(revisions => console.info(revisions)); console.info('platform: ' + await browserFetcher.platform()); console.info('product: ' + await browserFetcher.product()); const info1 = await browserFetcher.revisionInfo('389298'); const info2 = await browserFetcher.revisionInfo('771731'); const info3 = await browserFetcher.revisionInfo('385798'); console.info(info1); console.info(info2); console.info(info3); })();結果:
[ '389298', '771731' ] platform: win64 product: chrome { revision: '389298', executablePath: 'path\\node_modules\\puppeteer\\.local-chromium\\win64-389298\\chrome-win32\\chrome.exe', folderPath: 'path\\node_modules\\puppeteer\\.local-chromium\\win64-389298', local: true, url: 'https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/389298/chrome-win32.zip', product: 'chrome' } { revision: '771731', executablePath: 'path\\node_modules\\puppeteer\\.local-chromium\\win64-771731\\chrome-win\\chrome.exe', folderPath: 'pathp\\node_modules\\puppeteer\\.local-chromium\\win64-771731', local: true, url: 'https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/771731/chrome-win.zip', product: 'chrome' } { revision: '385798', executablePath: 'path\\node_modules\\puppeteer\\.local-chromium\\win64-385798\\chrome-win32\\chrome.exe', folderPath: 'path\\node_modules\\puppeteer\\.local-chromium\\win64-385798', local: false, url: 'https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/385798/chrome-win32.zip', product: 'chrome' }さいごに
次はBrowserクラスをやっていきたいと思います。
- 投稿日:2020-05-27T01:31:55+09:00
[保存版]最新Node.js for Raspberry Pi Zero / 1 (ARMv6向け)
ARMv6のサポート終了
2019年4月頃、Node.jsのVer.12のリリースとともにARMv6のビルドが提供されなくなりました。ARMv6を使うデバイスはだいぶ少なくなりましたが、ここにありますよ!Zero WHが!!
RFC: Consider retiring the PI1s ARMv6 (downgrading support to "experimental") · Issue #1677 · nodejs/build · GitHub
どうやら非公式ビルドというものを用意してくれているようです。ありがたや。Node.js unofficial-builds project
Node.js Unofficial Builds Project
GitHub - nodejs/unofficial-builds: Unofficial binaries for Node.js
非公式ビルドは
https://unofficial-builds.nodejs.org/download/release/v14.3.0/
以下にあるようです。最新ビルドを見ると公式と比べて数時間差でしょうか。誤差ですね!手動でインストール
まず初めに公式最新リリースで最新バージョンを確認 (もしかしたら都合悪く最新バージョンがビルドされていないかもしれないので、非公式Releaseを要確認。)
VERSION=v14.3.0 DISTRO=linux-armv6l wget https://unofficial-builds.nodejs.org/download/release/$VERSION/node-$VERSION-$DISTRO.tar.xz意外と時間かかります。終わったら、解凍。
sudo mkdir -p /usr/local/lib/nodejs sudo tar -xJvf node-$VERSION-$DISTRO.tar.xz -C /usr/local/lib/nodejs適当なエディタで
~/.profile
に追記~/.profile# Nodejs VERSION=v14.3.0 DISTRO=linux-armv6l export PATH=/usr/local/lib/nodejs/node-$VERSION-$DISTRO/bin:$PATH
.profile
の再読み込み. ~/.profile
これで完了。
参照: Installation · nodejs/help Wiki · GitHubアップデートの仕方
毎回これやるのはダルいし、作業ゲーがアホらしいのでアップデート方法の模索。
ちょっと調べるとn
というパッケージがあるが、最新バージョンを聞くとやっぱり公式ビルドの11.15.0を返す始末。当たり前だが。
となると自分で作るしかない。うん、そうしよう。update-nodejs.sh#!/bin/sh . ~/.profile old=`node -v` echo "現在のNode.jsのバージョンは$oldです" ver='' if [ $# -eq 1 ]; then ver="v$1" if [ $ver = $old ]; then echo "Node.js($ver)が既にインストールされています" return 0 fi else ver=`wget -qO- https://nodejs.org/dist/latest/ | sed -nE 's|.*>node-(.*)\.pkg</a>.*|\1|p'` if [ $ver = $old ]; then echo "Node.js($ver)は最新です" return 0 fi fi wget https://unofficial-builds.nodejs.org/download/release/$ver/node-$ver-$DISTRO.tar.xz if [ ! -e node-$ver-$DISTRO.tar.xz ]; then return 1 fi if [ -d /usr/local/lib/nodejs ]; then sudo rm -r /usr/local/lib/nodejs fi sudo mkdir -p /usr/local/lib/nodejs sudo tar -xJvf node-$ver-$DISTRO.tar.xz -C /usr/local/lib/nodejs sed -i -e "s/VERSION=$VERSION/VERSION=$ver/g" ~/.profile rm node-$ver-$DISTRO.tar.xz . ~/.profile echo "Node.js: $old -> `node -v`"これを実行するだけで常にlatestに更新されます。LTSとかは考慮してませんorz
source update-nodejs.sh
引数にバージョンを入れると無理やりそのバージョンに移行します。が、非公式ビルドにあれば、です。
source update-nodejs.sh 14.0.0
定期実行させる
どんなバグでも仕様変更でもかかってこいって人はCronに入れるとよいでしょう。ただ頻度はほどほどに。
中でsudoとか使ってたり環境変数変えてたりして割と雑なスクリプトなのでCronでの動作保証はしません。というかシェルスクリプト書いたの数回目なのでツッコミ大歓迎です。Cronは試してみたら追記します。
- 投稿日:2020-05-27T01:12:48+09:00
NestJSとGraphQLで開発用の環境を作成する
NestJS と GraphQL で開発用の環境を作成する
目次
- NestJS のアプリケーションを作成
- GraphQL の依存関係を構築する
- mysql(docker)を用意する
- mysql の依存関係を構築する
1. NestJS のアプリケーションを作成
NestCliを用いて NestJS のアプリケーションを構築する。
cli を install していない時は、上の URL から cli を install してアプリケーションを作成します。
$ nest new nestjs-graphql $ npm run start:devlocalhost:3000で下記画面が表示されることを確認します。
2. GraphQL の依存関係を構築する
Qiita 記事で記載しましたが、依存関係を解決していきます。
GraphQL を利用するのに必要な 4 つをインストールしていきます。
$ npm i --save @nestjs/graphql graphql-tools graphql apollo-server-expresslibrary の型定義で error がはかれないように、tsconfig.json を編集します。
tsconfig.json{ "compilerOptions": { "module": "commonjs", "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es2017", "sourceMap": true, "outDir": "./dist", "baseUrl": "./", "incremental": true, //ここから追記 "skipLibCheck": true //ここまで追記 }, "exclude": ["node_modules", "dist"] }公式ドキュメントをもとに GraphQL の依存関係を app.module に定義していきます。
src/app.module.tsimport { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { join } from 'path'; @Module({ imports: [ GraphQLModule.forRoot({ debug: false, playground: true, typePaths: ['./**/*.graphql'], definitions: { path: join(process.cwd(), 'src/graphql.ts'), outputAs: 'class', }, }), ], }) export class AppModule {}サーバーを起動し、play groundにアクセスして paly groud が表示されることを確認します。
$ npm run start:dev下記のように Play Ground が表示されます。
3. mysql(docker)を用意する
docker-compose.ymlとDockerfileを追加していきます。
$ touch docker-compose.yml $ touch Dockerfile現状のディレクトリ構成は、以下になる想定です。
$ tree -L 1 -I node_modules . ├── Dockerfile ├── README.md ├── dist ├── docker-compose.yml ├── nest-cli.json ├── package-lock.json ├── package.json ├── src ├── test ├── tsconfig.build.json └── tsconfig.jsonMySQL のみの docker を作成するので、起動に必要な設定を作成していきます。
FROM mysql:5.7docker-compose.ymlversion: '3.7' services: db: build: . command: --default-authentication-plugin=mysql_native_password restart: always tty: true ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: example MYSQL_DATABASE: develop最後に docker を起動して正常に動作するか確認します。
$ docker-compose up $ docker ps -a4. mysql の依存関係を構築する
公式ドキュメントを目安に依存関係を構築していきます。
$ npm install --save @nestjs/typeorm typeorm mysql上記のインストールが完了したら、app.module に必要な設定を記載していきます。お行儀が悪いですが、とりあえず動くように設定を記載していきます。
src/app.module.tsimport { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { TypeOrmModule } from '@nestjs/typeorm'; import { join } from 'path'; @Module({ imports: [ GraphQLModule.forRoot({ typePaths: ['./**/*.graphql'], definitions: { path: join(process.cwd(), 'src/models/graphql.ts'), outputAs: 'class', }, }), TypeOrmModule.forRootAsync({ useFactory: () => ({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: 'example', database: 'develop', entities: [__dirname + '/**/*.entity{.ts,.js}'], synchronize: true, }), }), ], }) export class AppModule {}上記で簡易的な設定が完了したと思うので、あとは適宜 GraphQL を記載していけば実装できます。
- 投稿日:2020-05-27T00:16:59+09:00
WSL 2 デビューするときの初期設定
はじめに
こんにちは。今回 MacBook Pro を新調したのですが、最近 Windows の最新動向が気になるので、 Windows も使えるようにしたいと思い、Bootcamp をセットアップすることにしました。その際、とても詳しくて役に立ったのはこの記事です
Mac で Windowsが使えるようになったその勢いで、Windows Insider Program にも登録し、話題の WSL 2 をいち早く試すことにしました
今回は MacBook Pro 13 (macOS 10.15.4) + Bootcamp + Windows 10 Home の組み合わせですが、純正の Windows 端末でもやることは同じだと思いますのでご参考になさってください。
今回のゴール
WSL 2 で VS Code を起動し、SFDX コマンドを実行するまでをゴールとします
最初にやること
Windows にログインし、WSL 2 をインストールします。管理者モードの Powershell からコマンドをいくつか実行するだけです。
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart wsl --set-default-version 2
その後、Ubuntu の LTS をインストールして、Linux の世界へ Go
ターミナルのプロンプトを整える
ターミナルのデザインは大事ですね。コーディングするときのモチベーションにかかわります。
私は時刻や改行を入れたい派なので、次の例のように
~/.bashrc
と~/.bash_profile
を作成します。~/.bashrcexport PS1=$'\n''\D{%Y.%m.%d} \A $ \W\[\033[31m\]\[\033[00m\]'$'\n> '~/.bash_profiletest -r ~/.bashrc && . ~/.bashrc開発環境を整える
余談ですが、どうやら Git は最初から Linux 内にインストールされている模様。
wsl git --version
Node.js
Node.js LTS のインストールには nvm がおすすめ。
https://docs.microsoft.com/ja-jp/windows/nodejs/setup-on-wsl2
sudo apt-get install curl curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash nvm install --lts nvm ls node -v npm -vSalesforce CLI
npm 経由で Salesforce CLI をインストールします。
npm install --global sfdx-cli sfdx forceVisual Studio Code
VS Code と WSL 用の拡張機能をインストールします。Linux 内ではなく Windows 内にインストールする点に注意です。
結果発表
VS Code を起動 左隅の
><
の緑色アイコンをクリックRemote-WSL: New Window
をクリックしましょう。左隅に
WSL: Ubuntu
が光ってること、ターミナルが1: bash
になってることを確認できますか? sfdx コマンドを実行できたら無事ゴールですおまけ
エクスプローラーで見たいときは、アドレス欄に
\\wsl$\Ubuntu\home\takahito
などと入力します。これで開発生産性がますます向上しそうです。それではまた。 Happy Coding!!