20210604のNode.jsに関する記事は5件です。

簡単にtypescript + express + mysql で簡易 webAPI サーバー作成

MySQL + express + TypeScript で作成する記事がなかったので,備忘録がてらに記事を作成します. 一旦,エラーハンドリングは考えません. promise-mysql を使用しましたが,mysql でも問題ないと思います. ソースコードはこちら. はてなブログにも投稿しています. 全体構成 ディレクトリ構成は以下 . ├── movies-ddl.sql ├── package.json ├── src │   ├── app.ts │   └── config │   └── index.ts ├── tsconfig.json └── yarn.lock 環境構築 node.js プロジェクトを初期化 yarn init -y pakage を install yarn add promise-mysql @types/mysql express yarn add -D typescript ts-node @types/express @types/node package.json に以下の記述を追加 { ... "main": "src/app.ts", "scripts": { "build": "tsc", "start": "nodemon" } ... } データベース movie-ddl.sql を作成 drop database if exists MOVIE; create database MOVIE CHARACTER SET UTF8; CONNECT MOVIE; drop user if exists 'app-user'@'%'; set global validate_password_policy=LOW; create user 'app-user'@'%' identified by 'PaAsW0rD'; grant all privileges on MOVIE.* TO 'app-user'@'%'; create table if not exists MOVIE ( ID serial primary key, NAME varchar(100) not null, CREATED_AT timestamp(3) default current_timestamp(3) not null, UPDATED_AT timestamp(3) default current_timestamp(3) not null ); INSERT INTO MOVIE(NAME) VALUES ('天気の子'); INSERT INTO MOVIE(NAME) VALUES ('サマーウォーズ'); INSERT INTO MOVIE(NAME) VALUES ('ジョゼと虎と魚たち'); MySQL で ddl を読み込む mysql -u root -p # パスワードを入力 root@localhost> source /PATH/TO/express_api/movies-ddl.sql .env ファイル .env ファイルを作成して,環境変数を読み込む 作成する.env ファイル # express PORT=4000 # DB DB_HOST="localhost" DB_PORT="3306" DB_USER="app-user" DB_PASSWORD="PaAsW0rD" DB_DATABASE="MOVIE" 読み込みコマンド export $(cat .env | grep -v ^# | xargs) 実装 config src/config/index.ts export default { /** * APIサーバーのPORT番号 */ port: parseInt(process.env.PORT, 10), /** * databaseの設定 */ db: { host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT, 10), user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE, multipleStatements: true, }, }; app src/app.ts import express from "express"; import * as mysql from "promise-mysql"; import config from "./config"; const app: express.Express = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.listen(config.port, () => { console.log(`Start on port ${config.port}.`); }); const connection = async () => { return await mysql.createConnection(config.db); }; // movie一覧取得 app.get("/movie", (req: express.Request, res: express.Response) => { connection() .then((connection) => { const result = connection.query("SELECT * FROM MOVIE"); connection.end(); return result; }) .then(function (rows) { res.send(rows); }); }); // movie単一取得 app.get("/movie/:movieId", (req: express.Request, res: express.Response) => { const movieId = req.params.movieId; connection() .then((connection) => { const result = connection.query("SELECT * FROM MOVIE WHERE ID = ?", [ movieId, ]); connection.end(); return result; }) .then(function (rows) { res.send(rows); }); }); // movie追加処理 app.put("/movie", (req: express.Request, res: express.Response) => { const name = req.body.name; connection() .then((connection) => { const result = connection.query("INSERT INTO MOVIE (NAME) VALUES (?)", [ name, ]); connection.end(); return result; }) .then(function (rows) { res.send(rows); }); }); // movie更新処理 app.patch("/movie/:movieId", (req: express.Request, res: express.Response) => { const movieId = req.params.movieId; const name = req.body.name; connection() .then((connection) => { const result = connection.query( "UPDATE MOVIE SET NAME = ? WHERE ID = ?", [name, movieId] ); connection.end(); return result; }) .then(function (rows) { res.send(rows); }); }); // movie削除処理 app.delete("/movie/:movieId", (req: express.Request, res: express.Response) => { const movieId = req.params.movieId; connection() .then((connection) => { const result = connection.query("DELETE FROM MOVIE WHERE ID = ?", [ movieId, ]); connection.end(); return result; }) .then(function (rows) { res.send(rows); }); }); 動作確認 API サーバーを起動 yarn start CURD を確認 READ 全権取得 curl -H "Content-Type: application/json" localhost:4000/movie/ | jq [ { "ID": 1, "NAME": "天気の子", "CREATED_AT": "2021-06-03T23:39:19.024Z", "UPDATED_AT": "2021-06-03T23:39:19.024Z" }, { "ID": 2, "NAME": "サマーウォーズ", "CREATED_AT": "2021-06-03T23:39:19.026Z", "UPDATED_AT": "2021-06-03T23:39:19.026Z" }, { "ID": 3, "NAME": "ジョゼと虎と魚たち", "CREATED_AT": "2021-06-03T23:39:19.026Z", "UPDATED_AT": "2021-06-03T23:39:19.026Z" } ] 単一取得 curl -H "Content-Type: application/json" localhost:4000/movie/1 | jq [ { "ID": 1, "NAME": "天気の子", "CREATED_AT": "2021-06-03T23:39:19.024Z", "UPDATED_AT": "2021-06-03T23:39:19.024Z" } ] CREATE 作成 curl -X PUT -H "Content-Type: application/json" localhost:4000/movie -d ' {"name": "青の通り道"}' {"fieldCount":0,"affectedRows":1,"insertId":4,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0} 確認 curl -H "Content-Type: application/json" localhost:4000/movie/4 | jq [ { "ID": 4, "NAME": "青の通り道", "CREATED_AT": "2021-06-03T23:42:42.477Z", "UPDATED_AT": "2021-06-03T23:42:42.477Z" } ] UPDATE 更新 curl -X PATCH -H "Content-Type: application/json" localhost:4000/movie/4 -d '{"name": "新聞記者"}' { "fieldCount": 0, "affectedRows": 1, "insertId": 0, "serverStatus": 2, "warningCount": 0, "message": "(Rows matched: 1 Changed: 1 Warnings: 0", "protocol41": true, "changedRows": 1 } 確認 curl -H "Content-Type: application/json" localhost:4000/movie/4 | jq [ { "ID": 4, "NAME": "新聞記者", "CREATED_AT": "2021-06-03T23:42:42.477Z", "UPDATED_AT": "2021-06-03T23:42:42.477Z" } ] DELETE 削除 curl -X DELETE -H "Content-Type: application/json" localhost:4000/movie/4 | jq { "fieldCount": 0, "affectedRows": 1, "insertId": 0, "serverStatus": 2, "warningCount": 0, "message": "", "protocol41": true, "changedRows": 0 } 確認 curl -H "Content-Type: application/json" localhost:4000/movie/ | jq [ { "ID": 1, "NAME": "天気の子", "CREATED_AT": "2021-06-03T23:39:19.024Z", "UPDATED_AT": "2021-06-03T23:39:19.024Z" }, { "ID": 2, "NAME": "サマーウォーズ", "CREATED_AT": "2021-06-03T23:39:19.026Z", "UPDATED_AT": "2021-06-03T23:39:19.026Z" }, { "ID": 3, "NAME": "ジョゼと虎と魚たち", "CREATED_AT": "2021-06-03T23:39:19.026Z", "UPDATED_AT": "2021-06-03T23:39:19.026Z" } ] まとめ MySQL + express + TypeScript で WebAPI サーバーを作成しました. 簡易的なものなので,Web アプリ作成時やポートフォリオにはアーキテクチャを考えて作り直した方がいいです. SQL を直接書きたくない or SQL を書かなくても O/R マッパーで十分,みたな状況だと TypeORM を使うと,アーキテクチャも作成してくれるので楽だということに気がつきました.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

discord.jsでのUserクラスとGuildMemberクラスの違い

雑記用 そもそもdiscord.jsとは DiscordのBotをJavaScriptで動かすためのいい感じのライブラリ。これの説明は他の記事にぶん投げます クラス(Class)とは ものの説明書のことです。(ここより引用:https://techplay.jp/column/482) つまり、「ユーザー」をあらわすクラスと、「サーバーの人」をあらわすクラスがあるわけです。 違い Userクラス (詳細:https://discord.js.org/#/docs/main/stable/class/User) ユーザー(サーバー内外問わず)をあらわす。アカウント作成日時やユーザータグ(#1234など)が確認できる。 GuildMemberクラス (詳細:https://discord.js.org/#/docs/main/stable/class/GuildMember) サーバー内のユーザーをあらわす。サーバーの参加日時やClientUser(今プログラムでログインしているBotのこと)にそのユーザーがBAN可能かなどを確認できる。 変換方法 User → GuildMember guild.member(/*Userクラスの値*/) でできる。 たとえばコマンドの場合で、送信者をGuildMemberにする場合は message.guild.member(message.author); でできる。 GuildMember → User client.users.cache.get(/*GuildMemberクラスの値*/.id) でできます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TypeScriptでBigQueryを操作する

この記事に関して BigQuery + Lambda + CloudWatch を利用して、APIから取得したデータをBigQueryに保存する定期実行バッチを実装する機会があり、Node.jsでBigQueryのテーブル作成、テーブルにInsertする方法を書き残したいなと思います。 環境 node v12.18.4 TypeScript サービスアカウントを作成する BigQueryへのアクセス権を取得するため、GCPのコンソールからサービスアカウントを作成します。 サービスアカウントのトークンを使用して、GCPのリソースとGoogleCloudAPIsへのアクセスが可能になります。 サービスアカウントのコンソールから秘密鍵を作成し、取得します。 ※サービスアカウントとはリソースと同等なので、安全に管理できているか常に気をつける必要があります。 公式ドキュメントでサービスアカウント保護、使用と管理のベストプラクティスが公開されています。 サービス アカウントの使用と管理のベスト プラクティス サービス アカウントを保護するためのベスト プラクティス Node.jsから @google-cloud/bigquery を使用する npm install @google-cloud/bigquery 取得したサービスアカウントの秘密鍵を使用してBigQueryにアクセスする import { BigQuery } from "@google-cloud/bigquery"; ... const bigQueryClient = new BigQuery({ credentials: { private_key: your_service_account_private_key, client_email: your_service_account_client_email }, projectId: your_gcp_project_id }); 対象データセットに対してテーブルを作成 BigQueryはテーブルをパーティションしないとフルスキャンになるため、パフォーマンス向上のためパーティション分割テーブルを今回の実装では作成しました。 // テーブルの存在確認をして、存在しなかったら作成 const isTableExist = await bigQueryClient .dataset(dataSetId) .table(tableId) .exists(); const options = { schema: schema, location: your_locaiton, timePartitioning: { type: "DAY" } }; await bigQueryClient.dataset(dataSetId).createTable(tableId, options); 作成したテーブルに対してデータをインサートする await bigQueryClient .dataset(dataSetId) .table(tableId) .insert(data); 注意した点 負荷を減らすため、APIからデータを取得するたびにテーブルにインサートするのではなく、APIからある程度まとまったデータセットを取得してからインサート処理を実行するようにし、インサート回数ができるだけ少なくなるよう注意しました。 参考文献 https://cloud.google.com/bigquery/docs/reference?hl=ja https://cloud.google.com/bigquery/docs/partitioned-tables?hl=ja https://github.com/googleapis/nodejs-bigquery
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsでBigQueryを操作する

この記事に関して BigQuery + Lambda + CloudWatch を利用して、APIから取得したデータをBigQueryに保存するバッチを実装する機会があり、Node.jsでBigQueryのテーブル作成、テーブルにInsertする方法を書き残したいなと思います。 環境 node v12.18.4 TypeScript サービスアカウントを作成する BigQueryへのアクセス権を取得するため、GCPのコンソールからサービスアカウントを作成します。 サービスアカウントのトークンを使用して、GCPのリソースとGoogleCloudAPIsへのアクセスが可能になります。 サービスアカウントのコンソールから秘密鍵を作成し、取得します。 ※サービスアカウントとはリソースと同等なので、安全に管理できているか常に気をつける必要があります。 公式ドキュメントでサービスアカウント保護、使用と管理のベストプラクティスが公開されています。 サービス アカウントの使用と管理のベスト プラクティス サービス アカウントを保護するためのベスト プラクティス Node.jsから @google-cloud/bigquery を使用する npm install @google-cloud/bigquery 取得したサービスアカウントの秘密鍵を使用してBigQueryにアクセスする import { BigQuery } from "@google-cloud/bigquery"; ... const bigQueryClient = new BigQuery({ credentials: { private_key: your_service_account_private_key, client_email: your_service_account_client_email }, projectId: your_gcp_project_id }); 対象データセットに対してテーブルを作成 BigQueryはテーブルをパーティションしないとフルスキャンになるため、パフォーマンス向上のためパーティション分割テーブルを今回の実装では作成しました。 // テーブルの存在確認をして、存在しなかったら作成 const isTableExist = await bigQueryClient .dataset(dataSetId) .table(tableId) .exists(); const options = { schema: schema, location: your_locaiton, timePartitioning: { type: "DAY" } }; await bigQueryClient.dataset(dataSetId).createTable(tableId, options); 作成したテーブルに対してデータをインサートする await bigQueryClient .dataset(dataSetId) .table(tableId) .insert(data); 注意した点 負荷を減らすため、APIからデータを取得するたびにテーブルにインサートするのではなく、APIからある程度まとまったデータセットを取得してからインサート処理を実行するようにし、インサート回数ができるだけ少なくなるよう注意しました。 参考文献 https://cloud.google.com/bigquery/docs/reference?hl=ja https://cloud.google.com/bigquery/docs/partitioned-tables?hl=ja https://github.com/googleapis/nodejs-bigquery
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node バージョン管理ツール n インストール時にエラー

問題 $ brew install n $ n lts をすると、以下のエラーが出ました。 Error: sudo required (or change ownership, or define N_PREFIX) 解決法 .bash_profile に以下を追加する。 export N_PREFIX=$HOME/.n export PATH=$N_PREFIX/bin:$PATH ターミナルを閉じて、開き直して確認。 $ which node /Users/[your-user]/.n/bin/node 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む