- 投稿日:2020-08-04T23:33:45+09:00
toJSONを用いて、JSONデータの返り値を制御する
JSONデータの返り値を制御する
例)petというJSONデータの場合
const pet = { name: 'Doggy' } console.log(JSON.stringify(pet))↓
{'name':'Doggy'}
というJSONデータが返ってくる。★返り値となるJSONデータを、toJSONを使って制御することができる
const pet = { name: 'Doggy' } pet.toJSON = function(){ return {} } console.log(JSON.stringify(pet))↓
{}
というJSONデータが返ってくる。つまり
toJSONで上書きされた値が、pet定数のJSONデータとして認識される
データベースのセキュリティ向上に利用
//mongooseを利用して、データベース型を設定 const mongoose = require('mongoose') const userSchema = new mongoose.Schema({ name: { type: String, //データ型の設定 required: true, trim: true }, password:{ type: String, required: true, }, tokens: [{ token: { type: String, require: true } }], }) //toJSONを用いて、外からuserObjectにアクセスした時に、返すメソッドと返さないメソッドを決める userSchema.methods.toJSON = function(){ const user = this const userObject = user.toObject() delete userObject.password delete userObject.tokens return userObject }↓
これで、userObjectは、toJSONで指定されている、passwordとtoken以外のデータを返すようになる。
- 投稿日:2020-08-04T22:53:06+09:00
bcryptでプレーンテキストをハッシュ化させる
ハッシュ化のメリット
・パスワードなどをデータベースに保存する時、プレーンテキストのまま保存すると脆弱性に繋がる。
・ハッシュ化したメッセージダイジェストから、元のメッセージを復元することは困難
→「インクリプション」…元のメッセージをとっておいて、それをハッシュ化したら同じハッシュ値になるかチェックすることで、同一性を確認する仕組みbcryptパッケージ
bcryptというnpmパッケージを利用すると、プレーンテキストをハッシュ化することができる。
・bcryptパッケージの使い方
const bcrypt = require('bcryptjs') const myFunction = async() => { const password = "password1234" const hadhedPassword = await bcrypt.hash(password, 8) //第一引数:ハッシュ化したい値、第二引数:roundをかける回数。公式推奨は8回 console.log(password) //元のパスワードを表示 console.log(hassedPassword) //ハッシュ化されたパスワードを表示 //元のパスワードとハッシュ化されたパスワードを比較し、同じものであるか確認 const isMarch = await bcrypt.compare('password', hashedPassword) } myFunction()値をハッシュ化させてからデータベースに組み込む
●Middlewareを利用してMongooseの振る舞い方をカスタマイズできる
Mongoose公式ドキュメント
「Middleware > Save/Validate」の項目
・validateする前、または後にイベントを設定できる。
・saveする前、または後にイベントを設定できる。→save()する前に、データベースに保存したい値をハッシュ化させることができる。
●例)
データベースに格納する前にpasswordをハッシュ化const mongoose = require('mongoose') const bcrypt = require('bcryptjs') const userSchema = new mongoose.Schema({ name: { type: String, //データ型の設定 required: true, trim: true }, password:{ type: String, required: true, } }) //middlewareを記述。saveする前にプレーンテキストをハッシュする userSchema.pre('save', async function(next){ //アローファンクションは使わない。このbindingは大事な役割を果たすものだから const user = this console.log('Middleware is working')//ミドルウェアが動いているか確認するためのテストコード if(user.isModified('password')){ //ハッシュ化されていないパスワードがある時 user.password = await bcrypt.hash(user.password, 8) }//ここで値がハッシュされる next() })
- 投稿日:2020-08-04T19:45:43+09:00
【Node.js】kuromoji.js + mecab-ipadic-neologdで形態素解析して遊ぶ
スクレイピングした文章を形態素解析したい!
node
ではjava
用に書かれたkuromoji
を移植したkuromoji.js
を使用するのが簡単っぽい。(自分調べ)しかしWeb上の文字は日々変化し、思ったように解析できない場合も多い。
そこでWeb上の資源を解析して作られている新語・固有表現に強いmecab-ipadic-NEologd
という辞書も導入する。
(+ベースはipadic
辞書)
- MeCab: Yet Another Part-of-Speech and Morphological Analyzer
- kuromoji - japanese morphological analyzer
- mecab-ipadic-neologd/README.ja.md at master · neologd/mecab-ipadic-neologd
- 日本語形態素解析エンジンKuromojiについて調べた - motacaplaのめう <-概念が分かりやすい?
環境
- Windows 10, git-bash, MINGW64(素直にlinux使ったほうが簡単です)
- busybox(UNIXコマンド群、後で導入)
- node v12.18.3
- npm v6.14.7
- kuromoji.js v0.1.2
kuromoji.js の導入
kuromoji.js
にはデフォルトで辞書が入っているため、使うだけなら非常に簡単。
サンプルのdicPath
を、node_module
内の辞書を参照するように変更する。$ npm install kuromojisample.jsvar kuromoji = require("kuromoji"); kuromoji.builder({ dicPath: "node_modules/kuromoji/dict" }).build(function (err, tokenizer) { // tokenizer is ready var path = tokenizer.tokenize("すもももももももものうち"); console.log(path); });実行すると形態素解析した結果が出力されるはず。
kuromoji-js-dictionary の導入
kuromoji.js
に新しい辞書を追加するには、その辞書をkuromoji
用に変換する必要がある。
これを支援してくれるスクリプトがあったので使用させてもらう。$ git clone https://github.com/sable-virt/kuromoji-js-dictionary.git $ cd kuromoji-js-dictionaly $ npm install
windows
環境では一部動かないので手作業で修正...package.json{ "scripts": { + "euc": "find ./neologd-seed -name '*.csv' -exec sh -c 'nkf -e --overwrite {}' ';'", + "tar": "find ./neologd-seed -name '*.csv' -exec sh -c 'tar -cvzf ./dict/neologd/$(basename {}).tar.gz {}' ';'", - "tar": "find ./neologd-seed -name '*.csv' -exec sh -c 'tar -cvzf ./dict/neologd/$(basename '{}').tar.gz {}' \\;", } }
euc
はgitのログを見る限り必要無くなったようだが、npm run convert
から消し忘れている様子...。
必要ないか断定できないのでログからリバートした。
また-exec
コマンドはwindows
では;
で終わらせる必要があるらしいので修正。ビルドするために他に
xz
とnkf
が必要なので、無い場合は適当に用意しておく。
linux
環境ならbrew
などで適当に取ってこれるがwindows
だとこれまた厄介。
xz
はbusybox
を使用し、nkf
はvictor
から適当なものを用意した。
それぞれ--help
コマンドが通れば追加完了。
その他足りないコマンドは各自で。辞書のコンバート
ここからはレドメ通りなのだが一応記録しておく。
./neologd-seed
のディレクトリに使用したい辞書(****.csv.xz
)を置いておく。
初めから以下のの辞書が置いてあるので、とりあえずそれを使用する。
- ../dict/mecab-ipadic-2.7.0-20070801.tar.gz (ベースの辞書)
- mecab-user-dict-seed.20180322.csv.xz
- neologd-adjective-verb-dict-seed.20160324.csv.xz
- neologd-common-noun-ortho-variant-dict-seed.20170228.csv.xz
- neologd-noun-sahen-conn-ortho-variant-dict-seed.20160323.csv.xz
# ./dict/neologd に変換した辞書を出力 $ npm run convert # ./dist に kuromoji.js 用の辞書を出力 $ ./bin/run
All done!!
って言われたら完成!
./dict
ディレクトリを自分のプロジェクトに持ってきて、dicPath
を変更すれば完成。
TypeError: Cannot read property 'lookup' of null
は辞書が見つからないエラー。
おま環か分からないが、package.json
からの相対パスで記載すればOKだった。新しい辞書の追加(mecab-ipadic-NEologd)
上記では予め用意された辞書を使用したが、
NEologd
はビルドすることで最新の辞書を作成することができる。(週2更新?)
ただそれはまた大変なので、リポジトリに定期的に保存?されているビルドされた辞書を使用する。
上記URLの ./seed からビルドされた辞書を取得できる。試しに
mecab-user-dict-seed.****.csv.xz
という辞書を追加する場合...
この辞書をダウンロードして、./neologd-seed
に放り込む。
前回のビルドの残骸(***.csv
)が残っている場合、消しておいてもよい。
その後、上記の「辞書のコンバート」の章と同じことをやれば完成だ。他の辞書もこれと同様の手法で導入できる(はず)。
NEologdの効能
NEologd
を今試しているサンプルに適用してみた。
これはある動画のチャット欄から単語として有用な名詞、動詞、形容詞を抽出し、出現数をカウントしたものである。
(ちなみにあんかけパスタを食べているシーンのチャット200件を対象としている)未適用の状態と比較すると「名古屋めし」や「あんかけパスタ」といういかにもな単語が、ちゃんと1ワードになっていることが確認できた。
2018年版と2020年版は特異な単語が無かったせいか大きな変化は無かった。
よって、Webの情報を処理する際には、NEologd
を使用したほうが効果的であろう。結論
kuromoji
とNEologd
を使ってどんどん形態素解析してこ!あとがき:
nodeでゴリゴリ書けるのは非常に助かる。
やろうと思えばブラウザでも実行できるのは強い。
Sudachi
ってのも試してみたいね。ぶっっっちゃけスクリプトをnodeで書き直せばこんなに引っかからないよねぇ。
けど、元ソースを読み解くのも面倒なので、環境側を合わせる方針にした。...WSLを使うのも手か?(まだ触ってないから未知の世界)
- 投稿日:2020-08-04T15:37:53+09:00
IBM Cloudのメール配信サービス(SendGrid)を使ってNode.js、Pythonからメール配信してみた!
背景
現在私が担当している案件で一般ユーザー向けのサービスを提供する予定で、ユーザー登録をした際などにメールをユーザーに送信する必要があるとのことで、メール送信サーバーをどうやって調達するかが課題となった。
お客様の方で用意できるメール送信サーバーで使えるものはないということだったので、IBM Cloud内で使用可能なサービスがないのかを調査した結果以下のサービスが利用できそうなので、実際に使えるのかどうか、利用方法はどんな感じかを実際にサービス登録して使ってみたのでこの記事にまとめました。
https://cloud.ibm.com/docs/email-delivery?locale=jaE メール配信について
SendGrid の IBM Cloud E メール配信サービスは、メール・リレー・サービスです。このサービスにより、スマート・ホストを使用してアウトバウンド・メール・サービスのリレーが可能になります。スマート・ホストは、SMTP サーバー、メール・クライアント、または SMTP を処理可能な任意のサービスまたはプログラム言語からの SMTP トラフィックをリレーします。 また、このサービスでは、メトリックの生成、E メール・リストの追跡、E メール・アクティビティー (E メールのバウンス、クリック、ドロップ、オープンなど) の追跡も行います。 このサービスには、ニュースレター支援や認証などの他の機能も用意されています。※なお、マニュアルには何が出来るかほとんど記載されていませんが、サポートに問い合わせたところ、IBM Cloud経由でSendGridに作成されたアカウントで選択したアカウント・タイプで使用可能なSendGridの機能はそのまま利用できるとのことです。
登録方法
https://cloud.ibm.com/classic/services/emaildelivery にアクセスし、Order Email Delivery Serviceのボタンをクリックする
Account Typeを選択し、Email Address、Username、Passwordを設定し、Continueボタンをクリックする
※UsernameとPasswordはSendGridアカウントのユーザー名、パスワードとして使用される。
登録が完了し一覧に表示されたら、ActionsよりAccess Vendor Portalを選択し、Send Gridのポータルにアクセスする
使い方
- 投稿日:2020-08-04T15:02:10+09:00
はじめてのAngular入門ガイド
Angularプロジェクトの概要と始め方を記載します。Versionの変更がたびたびあるので、内容はリンクは最新のVersionのページを確認すること。
社内教育に使っている資料なのでメモ書きです。
URL
アプリケーション生成
ng new application-nameでプロジェクト構成 - Routingの設定を聞かれるので > y - cssの設定は scssで起動コマンド
ng serveディレクトリ構成
全体感をつかむためにプロジェクトの構造を把握します。ディレクトリ構造を知っておくとバグ時にどのファイルが原因か可能性を絞れるようになります。
コンパイル関係
tsconfig
tsconfig.json: editorから参照されるファイル? (詳細は理解しておらず) tsconfig.base.json: app.json, spec.jsonの両方に継承されているコンパイル設定 tsconfig.app.json: 通常のコンパイル設定 tsconfig.spec.json : テスト用のコンパイル設定angular.json
Angularプロジェクトのビルドの設定などが記述されている。よく利用して重要なのは以下の3プロパティー。
- assets: 画像などを格納するdirectory
- styles: cssやscssなどを格納する。node_modulesに入っているscssなどを入れる。
- scripts: Javascriptファイルを読み込む
"assets": [ "src/favicon.ico", "src/assets" ], "styles": [ "src/styles.scss" ], "scripts": ["node_modules/libraryA/js/index.js"]おそらく最適化などの処理をしてもらえるので、Index.htmlをいじるのでなく上のファイルをいじることでJavaScriptやCSSなどを読み込むのがよい。
その他
とりあえずデフォルトのままで問題ないファイル。
src/test.s src/main.ts src/polyfills.ts src/index.htmlエディター設定ファイル
.editorconfig: エディター一般の構文設定 tslint.json: typescriptの構文設定環境設定ファイル
angular.jsonファイルのコンパイル設定で設定だれている。
envrionments.environment.tsAngularの構文
特に重要で理解したい概念
- Component
- Provider(Service)
- Module
理解したい構文
以下のdeclarations, imports, providers,exports。bootstrapはとりあえずとばしてよい
@NgModule({ declarations: [ AppComponent, UserListComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], exports: [], bootstrap: [AppComponent] }) export class AppModule { }とりあえずすすめたいところ
Getting Started, FundamentalsのComponent Interactionまで
モジュールとコンポーネント
export, import, declarationとcomponentの関係を正確に理解するのが重要
Yet to be written.
モジュールとコンポーネントの関係を理解するためのデモソースコード
URL: https://github.com/programmerkgit/angular-module-import-demoAngular Module
- Moduleのdeclareに記載されたComponentが利用できるようになる。
- componentは同じmodule内でdeclareされた他のcomponentを利用できる。
- componentは同じmodule内にimportされたModuleの中でdeclareかつexportされたcomponentを利用できる
- MainModuleがChildModuleをimportし、ChildModuleがGrandChildModuleをimportしている場合。ChildModuleがGrandChildModuleをexportすると、MainModuleからGrandChildModuleでexportしているModuleやcomponentにアクセスできる
MainModule declaration: [MainComponentA, MainComponentB], import: [ChildModule] ChildModule declaration: [ChildComponent, ExportedChildComponent] import: [GrandChildModule, ExportedGrandChildModule], export: [ExportedGrandChildModule] GrandChildModule declaration: [GrandChildComponent, ExportedChildComponent] export: [ExportedChildComponent] ExportedGrandChildModule declaration: [ExportedGrandChildComponent, ExportedExportedChildComponent] export: [ExportedChildComponent]
- 投稿日:2020-08-04T11:16:05+09:00
Node.jsでtmpに一時ディレクトリを作るにはfs.mkdtempSyncを使う
Node.jsで/tmpに一時的なディレクトリを作るには、fs.mkdtempSyncを使います。
const fs = require('fs') const dir = fs.mkdtempSync('/tmp/foo') console.log(dir) //=> "/tmp/foo4xeXpJ"
- 投稿日:2020-08-04T10:02:35+09:00
GitHub APIのレスポンスが 403 Forbidden になったら
User-Agent
ヘッダーは設定していますか??
https://docs.github.com/en/rest/overview/resources-in-the-rest-api#user-agent-requiredコード例
以下はissueを作成するコードです。
認証はパーソナルアクセストークンで行います。
PersonalAccessToken
,organization
,repository
はご自身のものに置き換えてください。github.tsimport https from 'https' const createIssue = async (title: string, body: string, labels: string[]): Promise<number> => { return new Promise((resolve, reject) => { const req = https.request({ method: 'POST', headers: { 'User-Agent': 'YourApp', // これ大事 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json', 'Authorization': `token ${PersonalAccessToken}` }, host: 'api.github.com', path: `/repos/${organization}/${repository}/issues`, }, (response) => { let res: any = '' response.on('data', (chunk) => { res += chunk }) response.on('end', () => { res = JSON.parse(res) resolve(res.id) }) response.on('error', (err: Error) => reject(err)) }) req.write(buildPayload(title, body, labels)) req.on('error', (err: Error) => reject(err)) req.end() }) } const buildPayload = (title: string, body: string, labels: string[]): string => { return JSON.stringify({ title, body, labels }) }まとめ
全ての原因がこれに当てはまるかは分かりませんが、私はこれで解決できました。
(@octokit/rest.jsなどを使った方が早いかもしれませんね)