ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
GakuNin RDM APIをNode.jsで操作する — プロジェクト作成からGitHub+Vercel自動デプロイまで

GakuNin RDM APIをNode.jsで操作する — プロジェクト作成からGitHub+Vercel自動デプロイまで

はじめに GakuNin RDMは、国立情報学研究所(NII)が提供する研究データ管理プラットフォームです。Open Science Framework(OSF)をベースに構築されており、APIを通じてプロジェクトの操作を自動化できます。 本記事では、Node.jsからGakuNin RDM APIを使って以下の操作を行う方法を紹介します。 プロジェクトの作成・設定 Wikiの作成・更新 メンバーの追加 GitHub連携 + Vercelによる自動デプロイ 事前準備 パーソナルアクセストークンの取得 GakuNin RDMにログイン 設定 > パーソナルアクセストークンに移動 新しいトークンを作成(スコープ:osf.full_read、osf.full_write) プロジェクトの初期化 mkdir rdm && cd rdm npm init -y npm install dotenv .envファイルにトークンを保存します。 GRDM_TOKEN=your_personal_access_token_here .gitignoreも作成しておきます。 .env node_modules/ APIクライアントの作成 GakuNin RDMのAPIはJSON:API形式を採用しています。まず汎用的なクライアントをlib/client.jsとして作成します。 lib/client.js require("dotenv").config(); const BASE_URL = "https://api.rdm.nii.ac.jp/v2"; const TOKEN = process.env.GRDM_TOKEN; if (!TOKEN) { throw new Error("GRDM_TOKEN is not set in .env"); } const headers = { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/vnd.api+json", }; async function request(method, path, body) { const url = `${BASE_URL}${path}`; const options = { method, headers }; if (body) { options.body = JSON.stringify(body); } const res = await fetch(url, options); if (!res.ok) { const text = await res.text(); throw new Error(`${method} ${path} failed (${res.status}): ${text}`); } if (res.status === 204) return null; return res.json(); } module.exports = { request, headers, BASE_URL }; ポイント: ...

校異源氏物語テキストDBのDTS(Distributed Text Services) APIの更新

校異源氏物語テキストDBのDTS(Distributed Text Services) APIの更新

概要 校異源氏物語テキストDBのDTS(Distributed Text Services) APIを更新したので、備忘録です。 背景 DTS(Distributed Text Services) APIは以下で説明されています。 https://distributed-text-services.github.io/specifications/ 以下の記事で、DTS APIの作成について紹介しました。 一方、以下を課題としていました。 今回開発したDTS APIも上記のガイドラインに非対応の箇所がある可能性がある点にご注意ください。 そこで、前回作成したAPIをv1とし、今回はdtsVersionの1-alphaに従ったv2のAPIを作成します。 API 以下がEntry Endpointです。v1とv2の違いは以下です。 v1 https://dts-typescript.vercel.app/api/v1/dts { "navigation": "/api/v1/dts/navigation", "@id": "/api/v1/dts", "@type": "EntryPoint", "collections": "/api/v1/dts/collections", "@context": "dts/EntryPoint.jsonld", "documents": "/api/v1/dts/document" } v2 https://dts-typescript.vercel.app/api/v2/dts { "@context": "https://distributed-text-services.github.io/specifications/context/1-alpha1.json", "dtsVersion": "1-alpha", "@id": "/api/v2/dts", "@type": "EntryPoint", "collection": "/api/v2/dts/collection{?id}", "navigation": "/api/v2/dts/navigation{?resource,ref,down}", "document": "/api/v2/dts/document{?resource,ref}" } 同様に、各種Endpointの記述を変更しています。 ビューアの改修 以下の記事で、DTSのビューア開発について紹介しました。 そして、以下を課題としていましたが、この点に対応できるように改修しました。 Navigation Endpointを使用していますが、現時点で複数階層には非対応です。 例えば、Navigation Endpointは以下のように記述します。 https://dts-typescript.vercel.app/api/v2/dts/navigation?resource=urn:kouigenjimonogatari.1&down=1 { "@context": "https://distributed-text-services.github.io/specifications/context/1-alpha1.json", "dtsVersion": "1-alpha", "@type": "Navigation", "@id": "/api/v2/dts/navigation?resource=urn:kouigenjimonogatari.1&down=1", "resource": { "@id": "urn:kouigenjimonogatari.1", "@type": "Resource", "document": "/api/v2/dts/document?resource=urn:kouigenjimonogatari.1{&ref}", "collection": "/api/v2/dts/collection?id=urn:kouigenjimonogatari.1", "navigation": "/api/v2/dts/navigation?resource=urn:kouigenjimonogatari.1{&ref}", "citationTrees": [ { "@type": "CitationTree", "citeStructure": [ { "@type": "CiteStructure", "citeType": "page", "citeStructure": [ { "@type": "CiteStructure", "citeType": "line" } ] } ] } ] }, "member": [ { "identifier": "5", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, { "identifier": "6", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, { "identifier": "7", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, { "identifier": "8", "@type": "CitableUnit", "level": 1, "parent": null, "citeType": "page" }, ... ] } 特に、CitationTreeを使って、階層を記述します。ビューアがこの情報を処理するように修正することで、以下のように、レベルごとのナビゲーションボタンが表示されるようにしました。 ...

mdx Iのオブジェクトストレージに対するproxyサーバの構築

mdx Iのオブジェクトストレージに対するproxyサーバの構築

概要 mdx Iのオブジェクトストレージに対するproxyサーバの構築に関する備忘録です。 背景 mdx Iの利用手引きにおいて、以下のように説明されています。 https://docs.mdx.jp/ja/index.html#オブジェクトストレージ mdxが提供するS3データサービス(DDN EXAScaler S3 Data Service)で取り扱うAPI仕様を記載したDataDirect Networks社のマニュアルです。 Tipsのオブジェクトストレージの利用方法例 と合わせてご確認ください。 https://docs.mdx.jp/ja/_downloads/b5d961f2c152387fa10ed951d5278f47/S3 Data Services 5.2.7 API Reference Guide.pdf こちらをGoogle NotebookLMに読み込ませ、corsの実装状況について確認しました。以下が回答です。 回答 資料 でBucket CORS Featureが未実装 であることが明記されているため、EXAScaler Access S3 APIに対して、ウェブブラウザ上で動作するJavaScriptなどから直接、異なるオリジン (例えば、APIのエンドポイントとは異なるドメインで提供されているウェブサイトのJavaScript)を通してリクエストを行うと、CORS(Cross-Origin Resource Sharing)の問題が発生し、通常はリクエストがブロックされます 。 これは、ウェブブラウザのSame-Origin Policy というセキュリティ上の仕組みによるものです。異なるオリジンからのリソースへのアクセスは、サーバー側が明示的に許可しない限り制限されます。CORSは、この許可の仕組みを提供するものですが、EXAScaler Access S3においては、この機能がまだ実装されていないため、サーバー側からのCORSヘッダーなどのレスポンスがなく、ブラウザはクロスオリジンリクエストを拒否する と考えられます。 したがって、プロキシサーバー などを利用して、クライアントサイドのリクエストを一旦プロキシサーバーに送り、そこからEXAScaler Access S3 APIにリクエストを行うことで、オリジンが一致するように見せかけるなどの回避策が必要になる場合があります。プロキシサーバーは、APIからのレスポンスに必要なヘッダーを付与する役割を担うこともできます。 ただし、これはCORSの問題を回避するための一つの一般的な方法であり、他にもサーバーサイドでAPIを公開する際にオリジンを一致させるなどの方法も考えられます。重要なのは、EXAScaler Access S3 API自体がCORSの仕組みをサポートしていない ため、クライアントサイドから直接クロスオリジンリクエストを行う際には、何らかの対策が必要になるということです。 対策 理解が間違っている点もあるかもしれませんが、上記の回答から、mdx Iのオブジェクトストレージに対するproxyサーバの構築を行うこととしました。 構築したproxyサーバのリポジトリは以下です。 https://github.com/nakamura196/s3-proxy 例えば、以下で指定したバケット上のファイルにアクセスできます。 https://s3-proxy.vercel.app/public/CETEIcean.css 一方、以下が直接アクセスした例です。 https://s3ds.mdx.jp/satoru196/public/CETEIcean.css 前者では、以下のようなレスポンスヘッダーが確認でき、CORSの設定がなされていることが確認できます。 access-control-allow-origin: * age: 0 cache-control: public, max-age=0, must-revalidate content-encoding: br content-type: text/css date: Sun, 23 Mar 2025 03:11:27 GMT etag: W/“3d5c-psb8jsgRM3DKYLgMVwi7Ns/AIhg” server: Vercel strict-transport-security: max-age=63072000; includeSubDomains; preload x-powered-by: Express x-vercel-cache: MISS x-vercel-id: hnd1::iad1::zbdgm-1742699486592-2b286aacd062 実装 Expressを用いて、以下のように実装しました。aws-sdkについては、AWS SDK for JavaScript v3に移行する必要があるようなので、この点はご注意ください。 ...

URLの引数で指定したIIIFマニフェストに対して、Mirador 3のannotationsプラグインを試す

URLの引数で指定したIIIFマニフェストに対して、Mirador 3のannotationsプラグインを試す

概要 URLの引数で指定したIIIFマニフェストに対して、Mirador 3のannotationsプラグインを試すことができるデモページを用意しました。 https://mirador-annotations.vercel.app/ iiif-contentまたはmanifest引数を使用することで、指定したIIIFマニフェストを対象にすることができます。 https://mirador-annotations.vercel.app/?iiif-content=https://dl.ndl.go.jp/api/iiif/1301543/manifest.json 本記事は、このデモページの作成に関する備忘録です。 背景 Mirador 3向けのアノテーション付与プラグインとして、mirador-annotationsがあります。 https://github.com/ProjectMirador/mirador-annotations 以下の記事で使い方の例を紹介しています。 そして、以下のデモページがすでに用意されていますが、URLの引数にIIIFマニフェストファイルを指定する機能は提供されていません。 https://mirador-annotations.netlify.app/ フォークと修正 URLの引数にIIIFマニフェストファイルを指定する機能の追加にあたり、上記のリポジトリをクローンしました。 https://github.com/nakamura196/mirador-annotations そして、以下の修正を加えました。 https://github.com/nakamura196/mirador-annotations/commit/18848ccb1fa51df821335ed76e7b9f4e974527d0 特に、以下の修正を加えています。 ... var params = new URL(document.location).searchParams; var manifest = params.get('iiif-content') || params.get('manifest') || 'https://iiif.harvardartmuseums.org/manifests/object/299843' var windows = []; if (manifest) { windows.push({ manifestId: manifest }); } ... これは、以下の実装を参考にしています。iiif-contentまたはmanifest引数でIIIFマニフェストファイルを参照するようでした。 https://projectmirador.org/embed/?iiif-content=https://iiif.io/api/cookbook/recipe/0001-mvm-image/manifest.json Vercelへのデプロイ設定 フォークしたリポジトリのソースコードをビルドした結果を、Vercelにデプロイしています。 デプロイにあたり、以下のような修正を加えました。 Output Directory、Install CommandおよびNode.jsのVersionを16.xに変更しています。 まとめ Mirador 3の利用にあたり、参考になりましたら幸いです。

Amazon LightsailでStrapiを動かす(SSL, 独自ドメイン)

Amazon LightsailでStrapiを動かす(SSL, 独自ドメイン)

概要 Amazon LightsailでStrapiを動かす機会がありましたので、その備忘録です。以下の記事を参考にしました。 https://zenn.dev/holykzm/articles/1e54cc25207657 インスタンス Node.jsを選択します。 メモリは1GB以上のものを選択してください。Lightsail上でビルドする場合、メモリ不足でエラーが発生します。 SSL、独自ドメイン 以下を参考にしてください。 https://zenn.dev/nakamura196/articles/5772d6c918508a#独自ドメインの付与 Static IPを付与して、Route 53で独自ドメインを設定し、以下を実行します。 sudo /opt/bitnami/bncert-tool ProxyPassの設定 (より適切な記述箇所があるかと思いますが、)以下を追記します。 /opt/bitnami/apache2/conf/httpd.conf # 末尾に以下を追加 ProxyPass / http://localhost:1337/ ProxyPassReverse / http://localhost:1337/ apacheの再起動 sudo /opt/bitnami/ctlscript.sh restart apache Strapi のインストール cd /opt/bitnami/apache2/htdocs/ npx create-strapi-app@latest backend --quickstart アプリが起動するので、Ctrl+Cなどで一旦停止します。 pm2 pm2のインストール sudo npm install pm2 -g server.jsの作成 cd /opt/bitnami/apache2/htdocs/backend vi server.js /opt/bitnami/apache2/htdocs/backend/server.js const strapi = require('@strapi/strapi'); strapi(/* {...} */).start(); ビルド cd /opt/bitnami/apache2/htdocs/backend NODE_ENV=production npm run build サーバの起動 NODE_ENV=production pm2 start server.js --name strapi 以下のように、strapiを起動できました。 ...

Node.js で XSLT を実行するサンプルリポジトリを作成しました。

Node.js で XSLT を実行するサンプルリポジトリを作成しました。

Node.js で XSLT を実行するサンプルリポジトリを作成しました。 https://github.com/ldasjp8/nodejs-xslt TEI/XMLファイルなどをNode.jsで処理する際の参考になりましたら幸いです。