Skip to content

JavaScript 変換

デフォルトでは、購読者は canonical な JSON レコードをそのまま受け取り ます。サーバーが別の形 — Markdown、異なる JSON 構造、プレーンテキスト 1 行 — を求めるときは、その購読者に変換スクリプトを設定し、ボディを 自分で組み立ててください。

契約

あなたが用意するのは関数 1 つです。

js
function transform(data, context) {
  // HTTP リクエストの「ボディ」を return する
}
  • 文字列を返す → そのまま送信されます(Markdown、プレーンテキスト、 フォームエンコード、…)。
  • オブジェクトまたは配列を返す → JSON.stringify(...) の結果が送信 され、Content-Typeapplication/json のままです。
  • それ以外undefined、数値、真偽値)を返す → 送信は意図的に 失敗します。Courier は空のデータや作りかけのデータを決して送りま せん。

スクリプトが制御するのはボディだけです。URL、メソッド、ヘッダー、 認証は購読者の設定どおりに維持されます。スクリプトを設定すると、静的な ボディパラメータはバイパスされます — ボディはあなた自身が組み立てます。

サンドボックス

スクリプトは、デバイス上の密閉された JavaScriptCore サンドボックスで実行 されます。

  • ネットワークなし、ファイルシステムなし、DOM なし、require なし、 setTimeout なし。
  • エラーや無限ループは送信を失敗させ、その理由は発行履歴に表示され ます。
  • console.log / warn / error はキャプチャされ、テストプレビュー でのみ表示されます。

context リファレンス

すべての値は文字列です。

フィールド
context.endpointName"My Obsidian relay"
context.url送り先の URL
context.kind"workout" | "sleep" | "note" | "weather"
context.nowこの発行の ISO-8601 タイムスタンプ
context.timeZone"Asia/Shanghai"
context.locale"zh-Hans"
context.appVersion / context.appBuild"1.0.0" / "1"
context.idempotencyKeyこの送信に付く Idempotency-Key

data リファレンス

data は、その購読者の種類に対応する canonical レコードです。日付は ISO-8601 文字列で(new Date(data.start) でパースできます)、オプションの フィールドは存在しないことがあります。

kind === "workout"

FieldType備考
idstringHealthKit の UUID — 冪等性の基点
activityTypestring"running""cycling""walking"、…
sourceobject{ name, bundleIdentifier?, productType?, version? }
start, endstringISO-8601
durationnumber
distanceMetersnumber?
activeEnergyKcal, totalEnergyKcalnumber?
elevationGainMetersnumber?
heartRateobject?{ averageBpm?, minBpm?, maxBpm? }
avgPaceSecPerKmnumber?
lapsarray?[{ index, start, duration, distanceMeters? }]
heartRateSeriesarray?心拍系列のトグルがオンのときのみ
routearray?ルートのトグルがオンのときのみ。大きい
metadataobject?HealthKit のメタデータをそのまま透過
schemaVersionnumber

kind === "sleep"

FieldType備考
idstring
nightOfstringこの一晩が帰属する日
inBedStart, inBedEndstring?
sleepStart, sleepEndstring
timeInBedSecnumber?
totalAsleepSecnumber
stagesobject{ awakeSec, remSec, coreSec, deepSec, unspecifiedSec }
awakeningsnumber
efficiencyPctnumber?0–100
vitalsobject?{ averageHeartRateBpm?, averageHRVms?, respiratoryRate?, oxygenSaturation?, wristTemperatureDeltaC? }
segmentsarray[{ stage, start, end }]、stage は inBed|awake|rem|core|deep|unspecified
sourcesarray[{ name, bundleIdentifier?, … }]
schemaVersionnumber

kind === "note"

FieldType備考
idstring
createdAtstringISO-8601
textstring記録された思考(入力または書き起こし)
sourcestring"text" | "audio"
metadataobject?
schemaVersionnumber

kind === "weather"

FieldType備考
idstring"{sleepID}:weather"
capturedAtstring測定時刻(≈ 起床時刻)
weatherDatestring対になる睡眠の nightOf
symbolNamestringSF Symbol 形式。例:"cloud.sun"
conditionTextstring例:"Cloudy"
temperatureC, apparentTemperatureCnumber
humidityPctnumber0–100
windKmhnumber
uvIndexnumber
precipitationChancePctnumber0–100
locationobject?{ lat, lon } — 座標のトグルがオンのときのみ
schemaVersionnumber

独自の JSON 構造:

js
function transform(data, context) {
  return {
    kind: "workout",
    activity: data.activityType,
    km: data.distanceMeters ? +(data.distanceMeters / 1000).toFixed(2) : null,
    minutes: Math.round(data.duration / 60),
    avgHr: (data.heartRate && data.heartRate.averageBpm) || null,
    at: data.start,
    via: context.endpointName,
  };
}

プレーンテキスト 1 行:

js
function transform(data) {
  const h = Math.floor(data.totalAsleepSec / 3600);
  const m = Math.round((data.totalAsleepSec % 3600) / 60);
  return "Slept " + h + "h" + m + "m on " + data.nightOf.slice(0, 10) +
         " (" + data.awakenings + " awakenings)";
}

注釈を Markdown の引用ブロックに:

js
function transform(data) {
  return "> " + data.text + "\n>\n> — " + data.createdAt;
}

ワークフロー

  1. 購読者エディタでスクリプトセクションを開き、.js ファイルを インポートするか、コードを貼り付けます。出発点として、コメントが ひととおり付いたテンプレートをアプリから受け取ることもできます。
  2. テストを押します。スクリプトが最近のサンプルに対して実行され、 実際に何かが送られる前に、出力ボディそのもの、コンソールログ、 エンドポイントの HTTP レスポンスを確認できます。
  3. 保存します。以後、この購読者へのすべての発行はスクリプトを通ります。 スクリプトのエラーは、壊れたデータを届ける代わりに、発行履歴上で 目に見える形で送信を失敗させます。

スクリプトは設定バックアップに含まれます

シークレット(キーチェーン保管、決して書き出されません)とは異なり、 変換スクリプトは設定バックアップに平文で含まれます — スクリプト内に 認証情報をハードコードしないでください。

自宅にて印刷 · © 2026 Xheldon