LoginSignup
1
1

More than 3 years have passed since last update.

Personiumのセルに ODataライブラリ o.js を使って読み書き

Posted at

はじめに

PDS(Personal Data Store) の OSS 「Personium」ですが、
肝心の個人データ管理には ODataWebDAV という標準化されたプロトコルを使用します。

今回はODataについて触り方を紹介します。Personium特有の制約事項などもあるので、
詳細はドキュメントを読むべきなのですが、
全部読んでいると日が暮れてしまいますので()、
ライブラリなどを使用して簡単に入門してみます。

Personiumについてはこちら → Personium とは何か?を個人的にまとめてみた

準備

o.js を使う前に今回使用する環境を準備します。

Personiumのデータ構造

Personiumでは、ユニットの中にセルというものを作成し、
1人1人がそれを管理します。

管理にあたって、セルの中には用途ごとにボックス を作成し、
ボックスの中には画像データなどの非構造データや、表データのような構造データを保存できます。

ボックス内の構成の管理に使用するプロトコルが WebDAV で、
ボックス内のコンテンツの1つとして、OData で管理できる表データがある形です。

セルの管理

Personiumのデモサーバーでは、いくつかのアプリがデフォルトでインストールされていて、
その中の「セルマネージャ」を使用すると簡単なセル管理が体験できます。

image.png

セルの管理の詳細については、セル管理(いずれ書きたい)の記事に任せるとして、ODataを作成していきます。

ODataの作成

今回はセルマネージャを使用して自分のセルに「odata-test」というボックスを作り、

image.png

その中に「sample」という名前で OData を作成しました。

image.png

EntityTypeの作成

ODataが作成できたら、次はその中に保存するデータの型(スキーマ)を定義していきます。

image.png

image.png

型「sampletype」

名前
title Edm.String
description Edm.String
num Edm.Int32
price Edm.Double

o.js で OData に触れてみよう

それでは触っていきます。

インストール

まずは o.js をインストールします。

npm install --save odata

準備

ここから先は oHandler というインスタンスを使い回します。

const {o} = require('odata');

const token = "<YOUR_TOKEN>";
const defaultHeaders = { "Content-Type": "application/json" }

const oHandler = o('https://<YOUR_CELL_FQDN>/odata-test/sample/', {
  headers: { "Authorization": `Bearer ${token}` , ...defaultHeaders },
});

こんな感じです。 <YOUR_TOKEN> に入るトークンはセルマネージャから取得することもできます。
(ROPCなどで認証して取ってくるのが正当な手順ですが・・・)

image.png

EntityType取得

まずはEntityTypeを取得してみます。EntityType取得

$metadata/EntityType を叩けばいいらしい。

const response = await oHandler
  .get('$metadata/EntityType')
  .query({
    $format:"json"
  });
console.log(JSON.stringify(response, null, 2)
{
  "d": {
    "results": [
      {
        "__metadata": {
          "uri": "https://<YOUR_CELL_FQDN>:443/odata-test/sample/$metadata/EntityType('sampletype')",
          "etag": "W/\"1-1588926355822\"",
          "type": "ODataSvcSchema.EntityType"
        },
        "Name": "sampletype",
        "__published": "/Date(1588926355822)/",
        "__updated": "/Date(1588926355822)/",
        "_AssociationEnd": {
          "__deferred": {
            "uri": "<略>/odatatest/sample/$metadata/EntityType('sampletype')/_AssociationEnd"
          }
        },
        "_Property": {
          "__deferred": {
            "uri": "<略>/odata-test/sample/$metadata/EntityType('sampletype')/_Property"
          }
        }
      }
    ]
  }
}

ちゃんと定義されていることが伺えますね。

なお、下記スクリプトでプロパティ一覧を取得すると

const response = await oHandler
  .get("$metadata/EntityType('sampletype')/_Property")
  .query({
    $format:"json"
  });
console.log(response.d.results.map(x => `${x.Name}: ${x.Type}`));
[
  'title: Edm.String',
  'description: Edm.String',
  'num: Edm.Int32',
  'price: Edm.Double'
]

いい感じです。

Entity作成

続いて、先程定義した型でEntityを登録してみます。Entity作成

const dat = {
  title: 'hoge',
  description: 'fuga',
  price: 100,
  num: 5
}
const response = await oHandler
  .post('sampletype', dat)
  .query({
    $format:"json"
  });

セルマネージャで確認してみます。

image.png

たくさん作ってみます。

image.png

できてる!!

なお、 num: 0.325 など、本来 Int32 型のプロパティに Double を入れたりすると、
「400 Bad Request」が返ってきます。

Entity取得

const response = await oHandler
  .get('sampletype')
  .query({
    $format:"json"
  });
console.log(response.d.results.map(x => ({ title: x.title, price: x.price})));

結果

[
  { title: 'hoge', price: 100 },
  { title: 'hoge1', price: 100 },
  { title: 'hoge2', price: 100 },
]

クエリももちろん書けます。

const response = await oHandler
  .get('sampletype')
  .query({
    $format:"json",
    $filter: "title eq 'hoge' and num eq 0"
  });
console.log(response.d.results.map(x => ({ title: x.title, num: x.num})));

結果

[ { title: 'hoge', num: 0 } ]

いいですね。

おまけ

使用した上でいくつか引っかかったポイントを紹介。

Proxy配下で使用する

o.js 内部で使用している node-fetch はデフォルトでは
プロキシ環境変数(http_proxy, https_proxy)は読んでくれません。

node-fetch をプロキシ環境で使う

そこで、上記のモジュールを使用させてもらいます。

npm install --save node-fetch-with-proxy

でもって、

const oHandler = o('<ODATA_ENDPOINT>');

global.fetch = require('node-fetch-with-proxy');

const response = await oHandler.get('hoge').query({});

といった形で、o 関数を実行した後にfetchを上書きします。

o関数ではこのように、呼ばれた際にブラウザか否かを判定して、
fetchがなければ polyfill を実行するようになっています。

// https://github.com/janhommes/o.js/blob/master/src/o.ts#L27

// polyfill fetch if we have no fetch
const env = typeof window !== "undefined" ? window : global;
if (!("fetch" in env) && !config.disablePolyfill) {
  require("cross-fetch/polyfill");
}

自前で polyfill して、 config.disablePolyfill を true にするでも良いのですが、
今回はとりあえずこれで。

終わりに

今回は o.js というライブラリを使用して ODataというプロトコルでデータを
触ってみる、という記事を書いてみました。

伝えたかったことは、ODataという標準化されているプロトコルを採用していることで、
既存のライブラリを使用することが可能であるという点です。

Personiumを使ってみたい、もっと知りたい、開発に参加したい、という方は
Personiumコミュニティ までお願いします!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1