20200301のNode.jsに関する記事は10件です。

Nuxt.jsのpluginsにaxiosの共通部品を実装する

はじめに

Nuxt.jsにてクライアントサイドのvueからサーバのREST APIを呼び出す際に、vue内のスクリプトにロジックを書くと、他の場所で流用できない。そのため、外部のjsに共通ロジックとしてサーバのAPIを呼び出す処理を記述したかったが、あまり良い例が無かったので、検討&実装してみた(正しいかは不明)
Vuexストア内でaxiosを使ってサーバAPIを呼び出すみたなことをやってる人も居たけど、それはちょっと違うだろう(というか気持ち悪い)ということで、pluginsに共通ロジックを作成することにした。

構成

修正する対象は以下の3ファイル(pages/index.vue , plugins/axios.js , plugins/api.js)

ROOT
 ├─.nuxt
 ├─assets
 ├─components
 ├─layouts
 ├─middleware
 ├─pages
 │      index.vue
 ├─plugins
 │      api.js
 │      axios.js
 ├─server
 ├─static
 ├─store
 └─test

axios.js

以下の記事を参考に、pluginsフォルダ配下にaxios.jsを作成する。
今回は記事のまま修正はしていない。このプラグインを作成することで、axiosでサーバアクセスする際、
リクエスト発生時、エラー発生時に処理をフックして任意の処理を実行することができる。
$axios.onResponseでレスポンス時にフックすることも可能。

https://axios.nuxtjs.org/extend

axios.js
export default function ({ $axios, redirect }) {
  $axios.onRequest((config) => {
    console.log('Making request to ' + config.url)
  })

  $axios.onError((error) => {
    const code = parseInt(error.response && error.response.status)
    if (code === 400) {
      redirect('/400')
    }
  })
}

api.js

このjsがapiを呼び出す共通部品。

api.js
export default function ({ $axios }, inject) {
  const api = new API($axios)

  inject('api', api)
}

class API {
  constructor (axios) {
    this.axios = axios
  }

  async getHoge () {
    const res = await this.axios.$get('http://localhost:3000')
    console.log(res)
  }
}

次の処理を入れることで、後述するvue内で $api としてアクセスすることができるようになる。

  inject('api', api)

ここまで作成したら、 nuxt.config.js 内の plugins に次のように記載する。

nuxt.config.js
  plugins: [
    '~/plugins/axios',
    '~/plugins/api'
  ],

idnex.vue

index.vueの<script>部分だけを抜粋。
asyncData() 内ではthisが使えないので、context.app.\$api.getHoge()
mounted() 内などのthisが使える箇所では、this.\$api.getHoge()
とすることで、api.jsに記載したaxiosの共通ロジックを呼び出すことができる。

index.vue
<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  asyncData (context) {
    context.app.$api.getHoge()
    return {
    }
  },
  mounted () {
    this.$api.getHoge()
  }
}
</script>

まとめ

この記述がNuxt.jsとして正しいかどうかは、少し微妙なところ。
そもそもAPIクラスを作成する必要が無く、inject('メソッド名', function)とすればよい。
しかし、今回作成したかったアプリケーションは、バックエンドが複数あり、
そのバックエンド毎に処理を実行する共通インスタンス(この例では\$api)を
作成したかったからこのようにしている。
\$backendA.getHoge(), \$backendB.getHoge() のような感じ。

参考

  • Axios Module
    https://axios.nuxtjs.org/
    なぜNuxt.jsの本家サイトにこの例が記載されていないのかが謎ってくらい「なるほどね」ってなった。
  • Nuxt.jsでaxiosの共通処理を作成し、API呼び出し処理をラップして使用する
    https://qiita.com/itouuuuuuuuu/items/4132e3b7ddf2cbf02442
    最初この記事を見つけたときは「おぉ!!」ってなった。次の2点を自分なりに改善してみたのが本記事。
    • export let axios;
      plugins/axios/index.js 内で export let axios; としている。
      axiosをexportしたかったからこのようにしたんだと思うけども、
      これだとESLintのimport/no-mutable-exports に引っかかってしまう。
    • import UserApi from '@/plugins/axios/modules/user'
      作成した共通部品をvue内で使用する際にimportしなければならない。
      これは地味にメンドイ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

node.jsをインストールの際、Chocolateyの提案を受けたのでインストールしてみた

概要

windowsでnode.jsをインストールしてみた。
ネットのインストール画像にはない、Chocolateyに関するインストール確認がでてきたたため、合わせてインストールしてみた。

環境

windows 10
node-v12.16.1-x64

インストール画面

Node.js Setup 2020_03_01 17_06_27.png
Node.js Setup 2020_03_01 17_06_44.png
Node.js Setup 2020_03_01 17_06_48.png
Node.js Setup 2020_03_01 17_06_53.png

以下が、Chocolateyに関するインストールの確認。
チェックをいれると、インストールされる。
Node.js Setup 2020_03_01 17_06_59 (1).png

Some npm modules need to be compiled from C/C++ when installing. If you want to be able to install such modules, some tools (Python 2 and Visual Studio Build Tools) need to be installed.
一部のnpmモジュールは、インストール時にC / C ++からコンパイルする必要があります。
そのようなモジュールをインストールできるようにするには、いくつかのツール(Python 2およびVisual Studioビルドツール)をインストールする必要があります。

Automatically install the necessary tools. Note that this will also install Chocolatey. The script will pop-up in a new window after the installation completes.
必要なツールを自動的にインストールします。 これにより、Chocolateyもインストールされることに注意してください。
インストールが完了すると、スクリプトが新しいウィンドウにポップアップ表示されます。

Alternatively, follow the instructions at https://github.com/nodejs/node-gyp#on-windows to install the dependencies yourself.
または、https://github.com/nodejs/node-gyp#on-windowsの指示に従って、依存関係を自分でインストールします。

Node.js Setup 2020_03_01 17_08_31.png

Node.js Setup 2020_03_01 17_09_47.png

この後には、以下の画面でChocolateyのインストールが始まった。
管理者_ Windows PowerShell 2020_03_01 17_14_33.png

なお、以下の画面ではなぜかエンターキーを押さないと処理が進まなかった。
管理者_ Windows PowerShell 2020_03_01 17_21_28.png

最後はこの画面でexitと入力してエンター
管理者_ Windows PowerShell 2020_03_01 17_29_08.png

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

nodejsのorマッパー sequelize のaccociaton

associationのまとめ

belongsTo

1つの関連をもつ。

  • 例) Players.belongsTo(Teams) Playersに外部キーteamIdが自動追加される。

hasOne

1つの関連をもつ。

  • 例) Players.hasOne(Profiles)

Profilesに外部キーplayerIdが自動追加される。include時、最初の1つのみ出力される。

hasMany

複数の関連をもつ。

  • 例) Players.hasMany(Profiles)

Profilesに外部キーplayerIdが自動追加される。include時、複数件出力される。

belongsToMany

多対多の中間テーブルを持つ。

  • 例1)Players.belongsToMany(Teams, { through: TeamPlayers })
    中間テーブル'TeamPlayers'が作成され、そこに外部キーteamId playerIdが自動追加される

  • 例2)Teams.belongsToMany(Players, { through: TeamPlayers })

    中間テーブル'TeamPlayers'が作成され、そこに外部キーplayerId teamIdが自動追加される

belongToとhasOneの違い

挙動はほぼ同じ。指定の順が変わっただけ。

belongsTo のサンプル

// model(テーブル)を定義
// 主キー`id`や`createdAt`、`updatedAt`は勝手に定義されるので記述不要
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Teams = sequelize.define('teams', {
    name: Sequelize.STRING,
});
Players.belongsTo(Teams, { foreignKey: 'team_id' })   // playersに外部キー'team_id'が作成される。foreignKeyを省略した場合、キャメルケースでid名'teamId'が自動生成される

// modelを元にDBテーブルの作成({force:true}オプションは、テーブルdrop&create)
await Players.sync({ force: true });
await Teams.sync({ force: true });

// レコードのcreate
const team1 = await Teams.create({ name: 'team1' });
const player1 = await Players.create({ name: 'player1', team_id: team1.id });

// レコード取得
const player = await Players.findById(player1.id, { include: Teams })

console.log(player.get({ plain: true }))

出力結果

{ id: 1,
    name: 'player1',
    createdat: 2019-08-29t02:36:21.464z,
    updatedat: 2019-08-29t02:36:21.464z,
    team_id: 1,
    team:
    { id: 1,
    name: 'team1',
    createdat: 2019-08-29t02:36:21.448z,
    updatedat: 2019-08-29t02:36:21.448z } }

以下でも、teams : players = 1 : n で取得できそうだが、できない

const team = await Teams.findById(team1.id, { include: Players})

出力結果

failed: sequelizeeagerloadingerror: players is not associated to teams!

hasOne のサンプル

// model(テーブル)を定義
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Profiles= sequelize.define('profiles', {
    name: Sequelize.STRING,
});
Players.hasOne(Profiles,{foreignKey:'player_id'})

// modelを元にDBテーブルの作成
await Players.sync({ force: true });
await Profiles.sync({ force: true });

// レコードのcreate
const player1= await Players.create({ name: 'player1' });
const profile1= await Profiles.create({ name: 'profile1', player_id: player1.id });
const profile2= await Profiles.create({ name: 'profile2', player_id: player1.id });

// レコードの取得
const player = await Players.findById(player1.id, { include: Profiles})

console.log(player.get({ plain: true }))

出力結果

{ id: 1,
    name: 'player1',
    createdAt: 2019-08-29T03:59:30.432Z,
    updatedAt: 2019-08-29T03:59:30.432Z,
    profile:
    { id: 1,
    name: 'profile1',
    createdAt: 2019-08-29T03:59:30.448Z,
    updatedAt: 2019-08-29T03:59:30.448Z,
    player_id: 1 } }

hasMany のサンプル

// model(テーブル)を定義
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Profiles= sequelize.define('profiles', {
    name: Sequelize.STRING,
});
Players.hasMany(Profiles,{foreignKey:'player_id'})

// modelを元にDBテーブルの作成
await Players.sync({ force: true });
await Profiles.sync({ force: true });

// レコードのcreate
const player1= await Players.create({ name: 'player1' });
const profile1= await Profiles.create({ name: 'profile1', player_id: player1.id });
const profile2= await Profiles.create({ name: 'profile2', player_id: player1.id });

// レコードの取得
const player = await Players.findById(player1.id, { include: Profiles})

// hasOneだと最初の1件しか取得できないがhasManyだと全て取得できる
console.log(player.get({ plain: true }))

出力結果

{ id: 1,
    name: 'player1',
    createdAt: 2019-08-29T04:13:05.396Z,
    updatedAt: 2019-08-29T04:13:05.396Z,
    profiles:
    [ { id: 1,
        name: 'profile1',
        createdAt: 2019-08-29T04:13:05.412Z,
        updatedAt: 2019-08-29T04:13:05.412Z,
        player_id: 1 },
    { id: 2,
        name: 'profile2',
        createdAt: 2019-08-29T04:13:05.428Z,
        updatedAt: 2019-08-29T04:13:05.428Z,
        player_id: 1 } ] }

belongsToMany のサンプル

// model(テーブル)を定義
// 主キー'id'や'createdAt'、'updatedAt'は勝手に定義されるので記述不要
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Teams = sequelize.define('teams', {
    name: Sequelize.STRING,
});
const TeamPlayers = sequelize.define('team_players', {
    name: Sequelize.STRING,
});

// 中間テーブル'TeamPlayers'を作成し、そこに'team_id'を追加する
Players.belongsToMany(Teams, { through: TeamPlayers, foreignKey: 'team_id' }) 
// 中間テーブル'TeamPlayers'を作成し、そこに'team_id'を追加する
Teams.belongsToMany(Players, { through: TeamPlayers, foreignKey: 'player_id' })

await TeamPlayers.sync({ force: true });
await Players.sync({ force: true });
await Teams.sync({ force: true });

// レコードのcreate
const team1 = await Teams.create({ name: 'team1' });
const team2 = await Teams.create({ name: 'team2' });
const player1 = await Players.create({ name: 'player1' });
player1.addTeam(team1,{ status: 'started' })
player1.addTeam(team2,{ status: 'started' })
const player2 = await Players.create({ name: 'player2' });
player2.addTeam(team1,{ status: 'started' })
player2.addTeam(team2,{ status: 'started' })

// レコード取得
const player = await Players.findById(player1.id, { include: Teams })
console.log(player.get({ plain: true }))

const team= await Teams.findById(team1.id, { include: Players})
console.log(team.get({ plain: true }))

出力結果

{ id: 1,
  name: 'player1',
  createdAt: 2019-08-29T05:56:11.200Z,
  updatedAt: 2019-08-29T05:56:11.200Z,
  teams:
   [ { id: 1,
       name: 'team1',
       createdAt: 2019-08-29T05:56:11.168Z,
       updatedAt: 2019-08-29T05:56:11.168Z,
       team_players: [Object] },
     { id: 2,
       name: 'team2',
       createdAt: 2019-08-29T05:56:11.184Z,
       updatedAt: 2019-08-29T05:56:11.184Z,
       team_players: [Object] } ] }

{ id: 1,
  name: 'team1',
  createdAt: 2019-08-29T05:56:11.168Z,
  updatedAt: 2019-08-29T05:56:11.168Z,
  players:
   [ { id: 1,
       name: 'player1',
       createdAt: 2019-08-29T05:56:11.200Z,
       updatedAt: 2019-08-29T05:56:11.200Z,
       team_players: [Object] },
     { id: 2,
       name: 'player2',
       createdAt: 2019-08-29T05:56:11.217Z,
       updatedAt: 2019-08-29T05:56:11.217Z,
       team_players: [Object] } ] }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

node-canvasで絵文字を扱う

ユーザ生成コンテンツは、OGPを画像化して見せるのがデファクトスタンダードのようになってきました。
node.jsから、画像処理をcanvasのように扱える node-canvas を使う人も多いのではないでしょうか。

その方法は色々紹介されています。例えばこちらの記事など。
node.jsではてなブログ風アイキャッチ画像を動的に生成する

このnode-canvasですが、デフォルトでは絵文字は描画ができません。

今回は、node-canvasで、絵文字を Twemoji の見た目で描画するモジュールの紹介です。

node-canvasで絵文字を扱う

node module を npm で公開しておきました。

$ npm install --save node-canvas-with-emoji 
const { createCanvas } = require('canvas');
const { fillTextWithTwemoji } = require('node-canvas-with-twemoji');

async function main () {
    const canvas = createCanvas(500, 300);
    const context = canvas.getContext('2d');

    context.font = '30px Arial';
    await fillTextWithTwemoji(context, '絵文字も描画?', 140, 160);
}

main();

localhost.png

提供しているのは fillTextWithTwemoji(context, text, x, y, options?) という関数です。
contextを渡す以外は、本家の CanvasRenderingContext2D.fillText のように扱えるようにしています。

ただし、
fillTextWithTwemoji は非同期(Promise)で扱われるため、Promise や async/await も利用する必要があります。
(関数内で絵文字画像をダウンロードしているため)

また、現時点(2020.03.01)ではイタリック書体や、maxWidth引数などに対応していません。
こちらで開発しているので何かあれば。 GitHub
スターがつくだけでもやる気が出て実装するかもしれません。

雑記

Twemojiではなく、Apple Color Emojiなど、絵文字フォントを使う方法もあるようです。
- Any emoji support?
- Colored Emoji

ただし、こちらは著作権周りで、実際に使う場合は注意が必要です。
- 「絵文字」の利用で気をつけた方が良いこと、安全な使い方について

雑記2

同じようなこと考えてる人もいました。
- node-canvas でカラー絵文字対応について考えてたこと

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

Node.js Expressフレームワークを使用する準備

はじめに

本格的な開発をするにはフレームワークを活用します。
フレームワークを活用することで効率よく、開発することが出来るようになります。

今回は「Express」というフレームワークを採用しました。

Express Generatorのインストール

Expressを使用するには、Express Generatorを使用するのが便利です。
まず、Express Generatorをインストールします。
コマンドプロンプトを立ち上げで、以下のコマンドでインストールします。

npm install express-generator - g

上記コマンドはグローバルインストールと呼ばれるインストール方法になります。
Express Generatorはプログラム中で使用するものではありませんので、グルーバルな領域にインストールします。
ですので、コマンドを打つ場所(カレントフォルダ)はどこでも良いです。

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

Node.js Expressフレームワークを使用する為の準備作業

はじめに

本格的な開発をするにはフレームワークを活用します。
フレームワークを活用することで効率よく、開発することが出来るようになります。

今回は「Express」というフレームワークを採用しました。

環境

OS:Windows 10 Pro 64bit
node.js:v12.16.1
npm:v6.13.4

Express Generatorのインストール

Expressを使用するには、Express Generatorを使用するのが便利です。
まず、Express Generatorをインストールします。
コマンドプロンプトを立ち上げで、以下のコマンドでインストールします。

npm install express-generator - g

上記コマンドはグローバルインストールと呼ばれるインストール方法になります。
Express Generatorはプログラム中で使用するものではありませんので、グルーバルな領域にインストールします。
ですので、コマンドを打つ場所(カレントフォルダ)はどこでも良いです。

確認

以下のコマンドでインストールされたか確認出来ます。

npm view express-generator version

今回は4.16.1がインストールされました。
ex_var.jpg

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

node.jsでswitchbotの温湿度計データ取得

switchbotの温湿度計を購入したので、node.jsでデータを取得し、s3にアップロードしてみた。

データの取得

データの取得にはnobleを使用した。
nodeのv9以降では動かないようなので、v8系をインストールすること。
nobleの使い方は割愛。

microbotの開発元?のOpenWonderLabsがAPI仕様を公開しているので、それを参照しながらデータを読み取る。
https://github.com/OpenWonderLabs/python-host/wiki/Meter-BLE-open-API
ビットの操作はとっても苦手なので、苦労した。
例えば、4バイト目の後ろ7ビットには温度のデータが入っているようなので、このようにして取得。

const temperature = data.readUInt8(4) & 0x7f;

&(ビット演算子)で0x7f(1111111)をビットANDして、後ろ7桁を切り出すらしい。

前3桁が欲しかったら、こんな感じで0xE0(11100000)をビットANDして、
さらにシフト演算子 >>> (0埋めバージョン)で後ろ5桁を溢れさせる。

var a = data.readUInt8(4) & 0xE0 >>> 5

web開発ばっかりやってた人間としては、このあたりはとっても苦手な領域。

データが取れたら fs でファイルに書き出す。
後で扱いやすいように moment.js を使って日時分秒をファイル名にした。

↓ソース全体(scan.js)

'use strict';

const noble = require('noble');
const fs = require('fs');
const moment = require('moment');

// living swithbot
const MAC = "xxxxxxx"; // switchbotのmacアドレス

const tmpDir = "/var/tmp/envdata/"; // データを保存したいディレクトリ

noble.on('stateChange', (state) => {
    if (noble.state === 'poweredOn'){
        noble.startScanning();
    } else {
        noble.on('stateChange', scanStart);
    }
});

noble.on('scanStart', () => {
    console.log('start scanning');
});

noble.on('scanStop', () => {
    console.log('stop scanning');
    process.exit(0);
});

noble.on('discover', (peripheral) => {
    if (peripheral.uuid === MAC) {
        noble.stopScanning();

        const data = peripheral.advertisement.serviceData[0].data;
        const deviceType = data.slice(0, 1).toString('ascii');
        const battery = data.readUInt8(2) & 0x7f;
        const temperature = data.readUInt8(4) & 0x7f;
        const humidity = data.readUInt8(5) & 0x7f;
        const time = moment().format('YYYY-MM-DD_HH:mm:ss');

        const jsonData = {
            "datetime": time,
            "battery": battery,
            "temperature": temperature,
            "humidity": humidity
        };

        // write to file
        fs.writeFileSync(tmpDir + time + '.log', JSON.stringify(jsonData));

        noble.stopScanning();
    }
});

s3へのアップロード

s3へのアップロードはいたって簡単です。

下準備

aws-sdk のライブラリを npm install する。
AWSのIAMでアップロード用のユーザ作ってAmazonS3FullAccessのポリシー(uploadだけだったら権限絞ったポリシーで良い気もする)付けて、そのcredential情報をjsonファイルに書き出しておく。

{
  "accessKeyId": "xxxxxxxxxxxxx",
  "secretAccessKey": "xxxxxxxxxx"
}

こんな具合。

S3への接続

こんな感じでs3オブジェクトをセットアップ。

AWS.config.loadFromPath('/home/pi/.aws/credential.json'); // 保存したcredentialファイルのパスを指定
AWS.config.update({region: 'ap-northeast-1'});

const s3 = new AWS.S3();

あとはアップロードしたいファイルの情報を整えて s3.putObject() でアップロード。

↓ソース(upload.js)

const AWS = require('aws-sdk');
const fs = require('fs');

AWS.config.loadFromPath('/home/pi/.aws/credential.json');
AWS.config.update({region: 'ap-northeast-1'});

const s3 = new AWS.S3();
const tmpdir = '/var/tmp/envdata/';


fs.readdir(tmpdir, (err, files) => {
  if (err) throw err;

  files.forEach( (file) => {
    var params = {
      Bucket: 'switchbot-room',
      Key: file
    };

    params.Body = fs.readFileSync(tmpdir + file);
    s3.putObject(params, (err, data) => {
      if (err) throw err;
      fs.unlinkSync(tmpdir + file, (err) => {
        if (err) throw err;
      });
    });
  });
});

自動起動設定

cron設定するだけ。

 */5 * * * * /usr/local/bin/node /home/pi/swithbot/scan.js
 */5 * * * * /usr/local/bin/node /home/pi/swithbot/upload.js

5分間隔でデータを取得して、アップロード。

今のところ問題なくデータが上がってます。

NextAction

次は、上がったデータを可視化したい。
QuickSight, Mackerel, ES + Kibana どれでやろうか検討中。chart.js使って自分で作ってもいいけど、
一番費用が掛からない方法がいいな。

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

LamdbaからS3内のファイルを操作したい

LamdbaからS3内を操作するメソッドで、よく使うものをメモ書き。

まずaws-sdkをrequireし、リージョンを指定します。
AWS SDKとは、AWSサービスをプログラムから操作できる開発キットです。

const AWS = require('aws-sdk');
const s3 = new AWS.S3({'region':'リージョン'});

ファイル作成・更新

ファイルを作成するには、putObjectメソッドを使用します。
S3に'test'というバケットがあり、その配下のsampleフォルダに'sample.json'というJSONファイルを作成します。

exports.handler = async (event) => {

  const putData = await s3.putObject(
    {
      Bucket:'test',
      Key:'sample/sample1.json',
      Body: JSON.stringify({})
    }).promise()
}

Bucket...バケット名
Kye...バッケト以下/ファイル名
Body...JSONファイル内に書きたい内容

実行すると、空のJSONファイルがS3に作成されます。

内容を記載したい場合はBodyのところに適当に入れます。

Body: JSON.stringify({name:'ai',age:20})

実行すると、sample.jsonの中に{"name":"ai","age":20}が追加されているのが確認できます。

ファイル取得

S3のファイルを取得するには、getObjectメソッドを使います。

exports.handler = async (event) => {
  const data = await s3.getObject(
    {
      Bucket:'test',
      Key:'test/sample1.json'
    }).promise()
    const obj = JSON.parse(data.Body) 
    console.log(obj.name,obj.age) //ai 20
}

先ほどと同様に、取得したいファイルの情報をBucket,Keyに指定します。
JSONをparseしてオブジェクトに変換することで、中身にアクセスすることができます。

ファイル削除

exports.handler = async (event) => {
 const deletes = await s3.deleteObject(
   {
     Bucket:'test',
     Key:'test/sample1.json'
   }).promise()
}

こちらも同様に削除したいファイルの情報をBucket、Keyに指定します。

実行すると、削除できたことが確認できます。
ちなみに、存在しないファイル名を指定した場合でもエラーにはなりません。
なのでtry~catchで囲み、エラーを出してくれるようにしてあげる必要があります。

exports.handler = async (event) => {
  try {
  const deletes = await s3.deleteObject(
    {
      Bucket:'test',
      Key:'sample/sample1XXX.json'
    }).promise().catch(err=>{
      throw new Error(err)
    })
  } catch (err){
    console.log(err)
  }
}

//実行結果 Error: NoSuchKey: The specified key does not exist.

存在しないファイル名を指定して実行すると、エラーになることが確認できました。

データの一覧を取得する

S3にどんなファイルがあるか分からない時、listObjectsV2メソッドで確認することがきます。

exports.handler = async (event) => {
    const params = {
      'Bucket':'test',
      'Prefix':'sample',
    }

    const lists = await s3.listObjectsV2(params).promise()
    lists.Contents.forEach((a) => console.log(a.Key))
}

実行すると、sampleフォルダ配下に何があるか確認できました。

実行結果
sample/
sample/sample1.json
sample/sample2.json
sample/sample3.json
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

azure app service で kintone アプリデータ公開

kintone のアプリデータをazure app service で公開してみます。

概要

プラグインを購入いただいたお客様のサポートやプラグインのバージョンアップなどで、kintone アプリを使ってどうにか出来ないかと調べています。
kintone アプリデータを外部に公開する外部サービスがありますが、簡単にできる反面、いろいろ制約があったりします。
azure app service で、kintone アプリデータを外部に公開する試作をしてみます。

環境

いつも使っている PC 環境で開発・テストして、azure へデプロイ。

  • 開発環境

  • azure環境

    • east asia (東京)

開発準備

vscode, node, npm あたりがそろっていれば OK。

Express ジェネレーター

アプリ名を指定すれば、基本的な一式をそろえてくれる優れもの。

アプリ名 kintone-view-test1 で作ってみます。

$ mkdir webapp
$ cd webapp
$ npx express-generator kintone-view-test1 --view pug --git
$ cd kintone-view-test1
$ npm install
...

アプリケーションの実行

npm start すると、http://localhost:3000 で参照できます。
CTL+C で、終了。

$ npm start

表示されるページ
2020-02-29_22h31_28.png

アプリケーションのデバッグ

vscode で、デバッグが出来るのがうれしい。
下記で、 wwww ファイルを起点とした設定が出来ます。

  • vscode で、kintone-view-test1\bin\www を開きます。
  • vscode の「デバッグと実行」をクリック
  • 「lunch.json ファイルを作成します。」をクリック
  • 「Node.js の実行とデバッグ(F5)」をクリック

2020-02-29_22h41_31.png

  • ブレークポイント
    • index.js にブレークポイントを設定
  • ブラウザから、http://localhost:3000 で参照
    2020-02-29_22h47_46.png

  • ブレークポイントで停止中は、変数にカーソルを当てると内容が表示されます

  • デバッグコンソール上で、変数を入力すると内容が確認できます。
    2020-02-29_22h50_59.png

アプリケーションのデプロイ

azure 環境へ、デプロイしてみます。

  • azure のアカウントを持っていて、以前からvscode で開発していれば、「Deploy to web app」をクリックするとデプロイが始まります。
    2020-02-29_23h03_05.png

  • kintone-view-test1 のフォルダーを指定
    2020-02-29_23h03_25.png
    2020-02-29_23h04_59.png

  • あとは、順番に node.js のバージョン等を指定します。

  • デプロイされた app をazure 上で確認
    2020-02-29_23h21_37.png

  • アプリの URL をクリックすると、実行結果が確認できます。
    2020-02-29_23h25_23.png

kintone アプリのレコード取得を組み込み

ここまでの作業で、azure 上でアプリを動作することが出来ました。
いよいよ kintone アプリのレコードを取得して、公開してみます。

kintone JS SDK のインストール

$ cd kintone-view-test1
$ npm install --save @kintone/kintone-js-sdk@v0.6.1

app.js の変更

とりあえず、kintone アプリレコードの照会画面用に、app.js 等を変更していきます。
「/customer」の URL でアクセスされたら、kintone の顧客アプリを表示するイメージです。
既存の「/users」と同じように処理を追加します。

app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var customerRouter = require('./routes/customer');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/customer', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

index.pug

index から、顧客一覧へのリンクを追加しておきます。

index.pub
extends layout

block content
  h1= title
  p Welcome to #{title}
  br
  a(href="./customer", title="顧客一覧") 顧客一覧

customer.js

アプリIDやURLなどは、開発用・本番用で切り替えが必要のので
kintone 接続用の情報は、モジュール化してまとめたほうがよさそうです。

customer.js
var express = require('express');
var router = express.Router();
const kintone = require('@kintone/kintone-js-sdk');

/* GET customers listing. */
router.get('/', function (req, res, next) {

    const kintoneAuth = new kintone.Auth();
    const username = 'xxxxxxxxx';
    const password = 'xxxxxxxxx';
    kintoneAuth.setPasswordAuth({ username: username, password: password });

    const domainName = 'xxxxxxxxx.cybozu.com';
    const kintoneConnection = new kintone.Connection({ domain: domainName, auth: kintoneAuth });
    const kintoneRecord = new kintone.Record({ connection: kintoneConnection });

    const finfos = [ 
        { label: '会社名', fcode: '会社名'},
        { label: '担当者名', fcode: '担当者名' },
        { label: 'メールアドレス', fcode: 'メールアドレス' }
    ];
    const fields = finfos.map((finfo) => {
        return finfo.fcode;
    });

    const appId = 549; // target appID
    const parm = {
        app: appId,
        query: 'order by $id',
        fields: fields
    };

    kintoneRecord.getRecords(parm).then((rsp) => {
        console.log('rsp', rsp);
        res.render('customer', {
            title: '顧客一覧',
            finfos: finfos,
            records: rsp.records
        });

    }).catch((err) => {
        // The promise function always reject with KintoneAPIExeption
        console.log(err.get());
        // res.render('forum', { title: 'rex0220 forum', user: 'error' });
    });

});

module.exports = router;

customer.pug

顧客一覧用のテンプレートです。
単純なテーブル構造だと簡単ですが、データ量が多くページ制御等があると少し面倒なので、グリッドライブラリを使ったほうがいいかもしれません。

customer.pug
extends layout

block content
  h1= title

  table(class="xp-customer-list")
    thead
      each finfo in finfos
        th #{finfo.label}
    tbody
      each rec in records
        tr
          each finfo in finfos
            td #{rec[finfo.fcode].value}

style sheet

顧客一覧用に少し手直し
見映えをよくする場合は、地道に手直し。

style.css
body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
  color: #00B7FF;
}

.xp-customer-list {
  background-color: aqua;
  width: 700px;
  font-size: 14px;
}

.xp-customer-list thead {
  background-color: azure;
}

取得結果

素のテーブルだけだと、いまいち。

2020-03-01_02h31_48.png

azure へデプロイ

初回と同様に「Deploy to web app」をクリックすると、デプロイされます。
2回目以降は、入力なしにそのまま続行します。

azure app service のログ

vscode から azure app service のログを確認できます。
console.log で、kintone レコードを出力したのが、表示されています。
保守・運用のことも考慮して、必要な情報を見やすくログに残したいですね。

2020-03-01_11h10_12.png

カスタムドメインでの公開

azure app service 内で、カスタムドメインの購入・割り当てが可能です。
チュートリアルに従って、手順を進めるだけなので簡単です。
お手軽に kintone アプリデータを一般に公開できますね。

2020-03-01_11h24_05.png

参考サイト

あとがき

vscode でデバッグ出来るのが、一番うれしい。
azure へのデプロイも vscode から簡単に実行できる。
Express の構成に慣れれば、開発が楽かもしれません。

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

azure app service で kintone アプリデータ公開その1

kintone のアプリデータをazure app service で公開してみます。

概要

プラグインを購入いただいたお客様のサポートやプラグインのバージョンアップなどで、kintone アプリを使ってどうにか出来ないかと調べています。
kintone アプリデータを外部に公開する外部サービスがありますが、簡単にできる反面、いろいろ制約があったりします。
azure app service で、kintone アプリデータを外部に公開する試作をしてみます。

こんな感じで、しくみを試作します。

kbrowserのAPI.png

環境

いつも使っている PC 環境で開発・テストして、azure へデプロイ。

  • 開発環境

  • azure環境

    • east asia (東京)

開発準備

vscode, node, npm あたりがそろっていれば OK。

Express ジェネレーター

アプリ名を指定すれば、基本的な一式をそろえてくれる優れもの。

アプリ名 kintone-view-test1 で作ってみます。

$ mkdir webapp
$ cd webapp
$ npx express-generator kintone-view-test1 --view pug --git
$ cd kintone-view-test1
$ npm install
...

アプリケーションの実行

npm start すると、http://localhost:3000 で参照できます。
CTL+C で、終了。

$ npm start

表示されるページ
2020-02-29_22h31_28.png

アプリケーションのデバッグ

vscode で、デバッグが出来るのがうれしい。
下記で、 wwww ファイルを起点とした設定が出来ます。

  • vscode で、kintone-view-test1\bin\www を開きます。
  • vscode の「デバッグと実行」をクリック
  • 「lunch.json ファイルを作成します。」をクリック
  • 「Node.js の実行とデバッグ(F5)」をクリック

2020-02-29_22h41_31.png

  • ブレークポイント
    • index.js にブレークポイントを設定
  • ブラウザから、http://localhost:3000 で参照
    2020-02-29_22h47_46.png

  • ブレークポイントで停止中は、変数にカーソルを当てると内容が表示されます

  • デバッグコンソール上で、変数を入力すると内容が確認できます。
    2020-02-29_22h50_59.png

アプリケーションのデプロイ

azure 環境へ、デプロイしてみます。

  • azure のアカウントを持っていて、以前からvscode で開発していれば、「Deploy to web app」をクリックするとデプロイが始まります。
    2020-02-29_23h03_05.png

  • kintone-view-test1 のフォルダーを指定
    2020-02-29_23h03_25.png
    2020-02-29_23h04_59.png

  • あとは、順番に node.js のバージョン等を指定します。

  • デプロイされた app をazure 上で確認
    2020-02-29_23h21_37.png

  • アプリの URL をクリックすると、実行結果が確認できます。
    2020-02-29_23h25_23.png

kintone アプリのレコード取得を組み込み

ここまでの作業で、azure 上でアプリを動作することが出来ました。
いよいよ kintone アプリのレコードを取得して、公開してみます。

kintone JS SDK のインストール

$ cd kintone-view-test1
$ npm install --save @kintone/kintone-js-sdk@v0.6.1

app.js の変更

とりあえず、kintone アプリレコードの照会画面用に、app.js 等を変更していきます。
「/customer」の URL でアクセスされたら、kintone の顧客アプリを表示するイメージです。
既存の「/users」と同じように処理を追加します。

app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var customerRouter = require('./routes/customer');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/customer', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

index.pug

index から、顧客一覧へのリンクを追加しておきます。

index.pub
extends layout

block content
  h1= title
  p Welcome to #{title}
  br
  a(href="./customer", title="顧客一覧") 顧客一覧

customer.js

アプリIDやURLなどは、開発用・本番用で切り替えが必要のので
kintone 接続用の情報は、モジュール化してまとめたほうがよさそうです。

customer.js
var express = require('express');
var router = express.Router();
const kintone = require('@kintone/kintone-js-sdk');

/* GET customers listing. */
router.get('/', function (req, res, next) {

    const kintoneAuth = new kintone.Auth();
    const username = 'xxxxxxxxx';
    const password = 'xxxxxxxxx';
    kintoneAuth.setPasswordAuth({ username: username, password: password });

    const domainName = 'xxxxxxxxx.cybozu.com';
    const kintoneConnection = new kintone.Connection({ domain: domainName, auth: kintoneAuth });
    const kintoneRecord = new kintone.Record({ connection: kintoneConnection });

    const finfos = [ 
        { label: '会社名', fcode: '会社名'},
        { label: '担当者名', fcode: '担当者名' },
        { label: 'メールアドレス', fcode: 'メールアドレス' }
    ];
    const fields = finfos.map((finfo) => {
        return finfo.fcode;
    });

    const appId = 549; // target appID
    const parm = {
        app: appId,
        query: 'order by $id',
        fields: fields
    };

    kintoneRecord.getRecords(parm).then((rsp) => {
        console.log('rsp', rsp);
        res.render('customer', {
            title: '顧客一覧',
            finfos: finfos,
            records: rsp.records
        });

    }).catch((err) => {
        // The promise function always reject with KintoneAPIExeption
        console.log(err.get());
        // res.render('forum', { title: 'rex0220 forum', user: 'error' });
    });

});

module.exports = router;

customer.pug

顧客一覧用のテンプレートです。
単純なテーブル構造だと簡単ですが、データ量が多くページ制御等があると少し面倒なので、グリッドライブラリを使ったほうがいいかもしれません。

customer.pug
extends layout

block content
  h1= title

  table(class="xp-customer-list")
    thead
      each finfo in finfos
        th #{finfo.label}
    tbody
      each rec in records
        tr
          each finfo in finfos
            td #{rec[finfo.fcode].value}

style sheet

顧客一覧用に少し手直し
見映えをよくする場合は、地道に手直し。

style.css
body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
  color: #00B7FF;
}

.xp-customer-list {
  background-color: aqua;
  width: 700px;
  font-size: 14px;
}

.xp-customer-list thead {
  background-color: azure;
}

取得結果

素のテーブルだけだと、いまいち。

2020-03-01_02h31_48.png

azure へデプロイ

初回と同様に「Deploy to web app」をクリックすると、デプロイされます。
2回目以降は、入力なしにそのまま続行します。

azure app service のログ

vscode から azure app service のログを確認できます。
console.log で、kintone レコードを出力したのが、表示されています。
保守・運用のことも考慮して、必要な情報を見やすくログに残したいですね。

2020-03-01_11h10_12.png

カスタムドメインでの公開

azure app service 内で、カスタムドメインの購入・割り当てが可能です。
チュートリアルに従って、手順を進めるだけなので簡単です。
お手軽に kintone アプリデータを一般に公開できますね。

2020-03-01_11h24_05.png

参考サイト

あとがき

vscode でデバッグ出来るのが、一番うれしい。
azure へのデプロイも vscode から簡単に実行できる。
Express の構成に慣れれば、開発が楽かもしれません。

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