API

JSON API

ここにあるすべてのページには JSON の対応物がある。キーも登録もいらない。ルートから始めてリンクをたどるか、OpenAPI の記述を読んでクライアントを生成する。

何を提供するか

API はコンテンツの木を映している。十二の伝統、それぞれから蒸留された原理、その原典、伝統横断の比較の層、合わせの羅針盤、そしてコーパス自身のレビュー状況が、いずれも JSON としてアドレスで指定できる。文書が長文の散文であるところでは、応答はそれを、コーパスが実際には持たないフィールドへ切り分けるのではなく、markdown として運ぶ。

読み取り専用である。提供されるのは GET だけで、すべての応答は公開されており、内容は CC BY-SA 4.0 でライセンスされている。

どのエンドポイントも、要求の本体もヘッダーもクエリパラメータも取らない——パスが要求のすべてである。同じ URL は常に同じバイト列を返す。言語がヘッダーではなく URL にあるのも、そのためである。

エンベロープ

すべての応答は同じ三つのトップレベルのキーを持つ。だからクライアントはどのエンドポイントも同じ扱いにでき、ルートの URL だけを知っていれば木の全体に届く。

data
ペイロードであり、エンドポイントごとに形が変わる唯一の部分。大半ではオブジェクトであり、二つのコレクション——諸伝統を並べるものと、一つの伝統の原典を並べるもの——では配列になる。
_links

関連するエンドポイントへの、名前つきのリンク。それぞれが href を持ち、たいていは関係を述べる rel を持つ。

  • self — このエンドポイント自身のアドレス。すべての応答に付く
  • parent — 木を一段上へ
  • html — 同じ内容を運ぶ、人が読めるページ。応答と同じ言語のもの
  • alternate — ルートに、言語ごとに一つ。同じ API の九つのロケールそれぞれの版であり、URL を推測するのではなくリンクをたどることで木の全体に届く
  • _links — コレクションの各項目がこれらの区画を自ら持つので、一覧はアドレスの集まりでもある
_meta

すべての応答に共通する、同じ三つのフィールド。

  • lang — この文書の言語——要求ごとに交渉された言語ではなく、それが来た木のロケール
  • license — 内容のライセンス、CC BY-SA 4.0
  • apiVersion — API のバージョン、現在は 1.0

OpenAPI の記述は、このオブジェクトに二つの任意のフィールド——エンティティタグと最終更新日のためのもの——も挙げている。今日はどちらにも値を入れるものがないので、両方とも「ときどき欠ける」ではなく「存在しない」ものとして扱うこと。

応答を一つ、そのまま丸ごと。これは全体を示せるほど小さい。コーパスの文書を運ぶエンドポイントは、数万文字に及ぶ。 /api/map.json
{
  "data": {
    "name": "Cross-Tradition Map",
    "description": "29 convergence themes, 13 held tensions, 41 preserved jewels across 12 traditions.",
    "themeCount": 27,
    "tensionCount": 13,
    "jewelCount": 41
  },
  "_links": {
    "self": {
      "href": "/api/map.json",
      "rel": "self"
    },
    "parent": {
      "href": "/api.json",
      "rel": "parent"
    },
    "convergence": {
      "href": "/api/map/convergence.json",
      "rel": "collection"
    },
    "divergence": {
      "href": "/api/map/divergence.json",
      "rel": "collection"
    },
    "jewels": {
      "href": "/api/map/jewels.json",
      "rel": "collection"
    },
    "html": {
      "href": "/en/map",
      "rel": "alternate",
      "type": "text/html"
    }
  },
  "_meta": {
    "lang": "en",
    "license": "CC BY-SA 4.0",
    "apiVersion": "1.0"
  }
}

エンドポイント

十三の形。そのうち三つは伝統の slug を取り、さらにそのうち一つは原典の識別子も取るので、行の数よりもはるかに多くの異なる URL がある。

十三のうち十一は、言語の接頭辞のもとにも存在する。どれがそうかは最後の列が示し、それによって何が得られ何が得られないかは、下の言語の節が述べる。

エンドポイント返すもの言語別
/api.jsonルートのインデックス。九つの言語それぞれのルートを含め、他のすべてのエンドポイントはそのリンクから届く。はい
/api/traditions.json十二の伝統すべてを、聖典、原理の数、先へのリンクとともに。はい
/api/traditions/{slug}.json /api/traditions/taoism.json一つの伝統——その聖典、そこから蒸留された原理の数、その原典の数。これは十二ある。はい
/api/traditions/{slug}/principles.json /api/traditions/taoism/principles.jsonその伝統から蒸留された原理を markdown で。これは十二ある。はい
/api/traditions/{slug}/books.json /api/traditions/taoism/books.jsonその伝統の原典。それぞれに一行の要約と、自身のアドレスが付く。これは十二ある。はい
/api/traditions/{slug}/books/{id}.json /api/traditions/taoism/books/ttc-ch01-10.json一つの原典と、そこから節ごとに読み出された言明。コーパスの原典ごとに一つ。数を仮定せず、上のコレクションに尋ねること。下に述べる理由により、どの言語でも英語である。いいえ
/api/map.json比較の層のインデックス。テーマ、緊張、保たれた語の数を伴う。はい
/api/map/convergence.json収斂マトリクスと、共有された主張を、伝統がそれに与える異なる理由から切り分ける分析。はい
/api/map/divergence.json保たれた緊張——伝統が本当に互いに矛盾し、その矛盾がそのまま立てられている箇所。はい
/api/map/jewels.json原語のまま保たれた語と、それらが置かれている合わせの羅針盤および構造分析。はい
/api/compass.json合わせの羅針盤の全体を markdown で。AI アシスタントに貼り込むならこの形である。はい
/api/review-status.json検証がどこまで進んでいるかを伝統ごとに——引用が確かめられているか、その伝統の内側からのレビュアーが確保されているか。コーパスを権威あるものとして述べる前に、これを読むこと。はい
/api/openapi.json上のすべての記述であり、二つの木の両方を覆う。これは一つだけであって、言語ごとに一つではない。いいえ

このパスの下では、これ以外に何も提供されない。ここに載っていないエンドポイントは存在せず、権威はルートのインデックスにある——それは解決するエンドポイントにしかリンクしない。

試してみる

出発点はルートのインデックスである——小さく、そして各言語のルートを含め、他のすべてのエンドポイントがそこにぶら下がっている。

curl -s https://distill.family/api.json

OpenAPI の記述

OpenAPI 3.1 の文書が、上のすべてのエンドポイントを、エンベロープとリンクのスキーマとともに記述する。ジェネレータをそれに向けてもよいし、ただ読んでもよい。

/api/openapi.json

言語の接頭辞を持つエンドポイントは、テンプレートのままにせず、ロケールごとに一つずつ書き出してある。生成されたクライアントは、一覧を持たないテンプレートに値を差し込めないし、記述されたすべてのパスが実際に解決することを主張するビルドの検査も、テンプレートをたどることはできない——だから列挙しておくことで、ローカライズされた木の全体をその主張のもとに置ける。

ここで対話的なエクスプローラーに描かせていないのは、意図してのことである。このサイトは、スクリプト、スタイル、ネットワーク接続を自らのオリジンからのみ許すコンテンツセキュリティポリシーを送っており、エクスプローラーはどれも他所から読み込まれる——だから埋め込めば、黙って失敗するか、すべての訪問者に対してそのポリシーを緩めることになる。文書を取得して、すでに信頼している道具で開くこと。

言語

同じエンドポイントを提供する木が二つある。正規のものは英語である。もう一方は言語の接頭辞を持ち、このサイトが支える九つの言語それぞれについて一度ずつ構築される。

/api/es.json

言語はパスの一区画であって、交渉ではない。クエリパラメータは読まれず、Accept-Language ヘッダーも読まれない——これは手落ちではなく、設計上の決定である。どのエンドポイントも事前レンダリングされる。ハンドラーはビルド時に一度だけ走り、そのとき交渉する相手の要求は存在せず、できあがったファイルがそのまま全員に配信される。ヘッダーによって変わりようのない応答は、自らの言語を URL に載せるほかない。そこであればアドレスとして指定でき、リンクでき、キャッシュできる。

九つのいずれでもない言語の区画は 404 を返す。他の言語の URL のもとで英語を配信し、キャッシュ層にそれを保持させるほうが悪い——言語をパスに置くことの眼目は、アドレスが返ってきたものについて本当のことを告げる、という点にある。

検証すべき理由はもう一つある。言語のリゾルバが返す値は、コーパスを読むときにファイルシステムのパスを組み立てるのに使われる。だから要求からそのまま取った値は、コンテンツの木の外にあるファイルを求める手段になりうる。リゾルバは何かを返す前に、支える言語の閉じた一覧に照らして確かめるので、どのように呼ばれても、そこに無い区画を出すことはできない。上の 404 は誠実さの話であり、こちらは安全の話である。

一つの層はまったく翻訳されていない。個々の原典はどこでも英語である。それらの翻訳が存在しないからである——そのためこれらのエンドポイントは英語の木からのみ提供され、言語の接頭辞を持つ原典のコレクションは、各項目を英語の文書へリンクし直す。その文書自身も、そのとおりに自らについて報告する。

それ以外の場所では、翻訳は木ごとではなく文書ごとである。すべての応答は、抱えている文書が翻訳されたかどうかを示すフラグを運び、その言語に翻訳のない文書は、何も返さないのではなく英語へ退避する。だから URL ではなくフラグを読むこと。

そしてそのフラグは狭く読むこと。それが記録するのは、翻訳が存在すること、そしてそこから荷重を担うものが失われていないことである——見出し、引用、出典、保たれた語は、いずれも在るかどうかを確かめてある。翻訳が正確であることは記録しない。このコーパスのいかなる部分も、母語話者が目を通してはいない。翻訳された文書は、検証された本文としてではなく、用を足す訳文として扱うのがよい。ルートのエンドポイントは、クライアントに見つけさせるのではなく、自らの応答のなかでそう述べている。

ヘッダーとキャッシュ

クロスオリジンの要求はどのホストからも許されているので、どこで配信されているページからでも直接取得できる。公表されるのは GET と OPTIONS だけである。

応答はブラウザで五分、共有キャッシュで一時間キャッシュできる。静的ファイルサーバーの背後にある静的ファイルであり、サーバーはそれぞれに弱いエンティティタグを付けて送るので、条件付きの要求が働く。

使う

蒸留された内容は クリエイティブ・コモンズ 表示-継承 4.0 (新しいタブで開きます) でライセンスされている。使い、引用し、その上に築いてよい——Distill.family に帰属を示し、築いたものを同じ条件でライセンスすること。聖典の引用はパブリックドメインの版によるもので、特定の翻訳に拠った箇所では本文中に出典を示している。

データとともに携えるべきことが二つある。引用はそれらの版に照らして一字ずつ検証してあるが、十二の伝統のいずれについても、その内側の研究者がこれらの読みを承認したわけではない。レビュー状況のエンドポイントが、その点がどこまで進んでいるかを伝統ごとに正確に報告する。

そして立場は引き受けたものであって、中立ではない。ここでは伝統を、互いに補完しうる部分的な見方として扱っており、その大半はそれを退けている。このデータの上に築かれるものは、その選択を引き継ぐ。だから黙って渡すよりも、言い直しておくほうがよい。