Skip to content

Transformation JavaScript

Par défaut, un abonné reçoit l'enregistrement JSON canonical tel quel. Quand votre serveur attend autre chose — du Markdown, une autre forme de JSON, une simple ligne de texte — attachez un script de transformation à cet abonné et construisez le corps vous-même.

Le contrat

Vous fournissez une fonction :

js
function transform(data, context) {
  // renvoyer le CORPS de la requête HTTP
}
  • Renvoyer une chaîne → envoyée telle quelle (Markdown, texte brut, encodage formulaire, …).
  • Renvoyer un objet ou un tableauJSON.stringify(...) est envoyé, Content-Type reste application/json.
  • Renvoyer autre chose (undefined, un nombre, un booléen) → l'envoi échoue, à dessein. Courier n'envoie jamais de données vides ou à moitié construites.

Le script ne contrôle que le corps. URL, méthode, en-têtes et authentification restent tels que configurés sur l'abonné. Avec un script attaché, les paramètres de corps statiques sont ignorés — c'est vous qui construisez le corps.

Le bac à sable

Les scripts s'exécutent sur l'appareil dans un bac à sable JavaScriptCore hermétique :

  • Pas de réseau, pas de système de fichiers, pas de DOM, pas de require, pas de setTimeout.
  • Les erreurs et les boucles infinies font échouer l'envoi et la raison apparaît dans l'historique d'envoi.
  • console.log / warn / error sont capturés et affichés uniquement dans l'aperçu Tester.

Référence de context

Toutes les valeurs sont des chaînes :

ChampExemple
context.endpointName"My Obsidian relay"
context.urll'URL de destination
context.kind"workout" | "sleep" | "note" | "weather"
context.nowhorodatage ISO-8601 de cet envoi
context.timeZone"Asia/Shanghai"
context.locale"zh-Hans"
context.appVersion / context.appBuild"1.0.0" / "1"
context.idempotencyKeyl'Idempotency-Key que portera cet envoi

Référence de data

data est l'enregistrement canonical du type de l'abonné. Les dates sont des chaînes ISO-8601 (new Date(data.start) pour les analyser) ; les champs facultatifs peuvent être absents.

kind === "workout"

FieldTypeNotes
idstringUUID HealthKit — la racine de l'idempotence
activityTypestring"running", "cycling", "walking", …
sourceobject{ name, bundleIdentifier?, productType?, version? }
start, endstringISO-8601
durationnumbersecondes
distanceMetersnumber?
activeEnergyKcal, totalEnergyKcalnumber?
elevationGainMetersnumber?
heartRateobject?{ averageBpm?, minBpm?, maxBpm? }
avgPaceSecPerKmnumber?
lapsarray?[{ index, start, duration, distanceMeters? }]
heartRateSeriesarray?seulement si l'option série FC est activée
routearray?seulement si l'option parcours est activée ; volumineux
metadataobject?métadonnées HealthKit transmises telles quelles
schemaVersionnumber

kind === "sleep"

FieldTypeNotes
idstring
nightOfstringle jour auquel cette nuit est rattachée
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"

FieldTypeNotes
idstring
createdAtstringISO-8601
textstringla pensée capturée (tapée ou transcrite)
sourcestring"text" | "audio"
metadataobject?
schemaVersionnumber

kind === "weather"

FieldTypeNotes
idstring"{sleepID}:weather"
capturedAtstringmoment de la mesure (≈ heure du réveil)
weatherDatestringle nightOf du sommeil associé
symbolNamestringstyle SF-Symbol, par ex. "cloud.sun"
conditionTextstringpar ex. "Cloudy"
temperatureC, apparentTemperatureCnumber
humidityPctnumber0–100
windKmhnumber
uvIndexnumber
precipitationChancePctnumber0–100
locationobject?{ lat, lon } — seulement avec l'option coordonnées activée
schemaVersionnumber

Exemples

Une forme JSON personnalisée :

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,
  };
}

Une ligne de texte brut :

js
function transform(data) {
  const h = Math.floor(data.totalAsleepSec / 3600);
  const m = Math.round((data.totalAsleepSec % 3600) / 60);
  return "Dormi " + h + " h " + m + " min le " + data.nightOf.slice(0, 10) +
         " (" + data.awakenings + " réveils)";
}

Un bloc de citation Markdown pour les annotations :

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

Marche à suivre

  1. Dans l'éditeur d'abonné, ouvrez la section script et importez un fichier .js ou collez du code. L'app peut vous fournir un modèle entièrement commenté pour démarrer.
  2. Appuyez sur Tester : le script s'exécute sur un échantillon récent et vous voyez le corps exact produit, les journaux de console et la réponse HTTP du point de terminaison — avant tout envoi réel.
  3. Enregistrez. Désormais, chaque envoi vers cet abonné passe par votre script ; les erreurs de script font échouer l'envoi de façon visible dans l'historique d'envoi plutôt que de livrer n'importe quoi.

Les scripts font partie des sauvegardes de configuration

Contrairement aux secrets (trousseau, jamais exportés), les scripts de transformation sont inclus en clair dans les sauvegardes de configuration — n'y codez pas d'identifiants en dur.

Imprimé chez vous · © 2026 Xheldon