Een dating-app op basis van brieven, niet van gezichten!

main

Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.

3.6 kB Ruw bestand
import { Postbode } from "./plugin";

/*
 * Het logboek van het toestel: wat er een native plugin in gaat en wat eruit komt. Dit zit ook in
 * de release, want een fout die je niet kunt uitlezen is een fout waar je niets aan hebt — wie met
 * een toestel voor je staat waarop het misgaat, is uit te lezen met
 *
 *   adb -s <serial> logcat -s Liefdesbrieven
 *
 * (de eigenaar moet daarvoor ontwikkelaarsopties en usb-foutopsporing aanzetten en de computer
 * eenmalig toestaan; zonder dat komt er niemand bij). De regels blijven op het toestel: ze gaan
 * naar het Android-logboek en nergens anders heen — geen server, geen bestand, geen tweede partij.
 * Andere apps kunnen er niet bij, dat kan sinds Android 4.1 alleen het systeem zelf.
 *
 * Waarom via de plugin en niet met console.log: Capacitor stuurt de console van de webview alleen
 * naar logcat in een debug-build. Die brug helemaal openzetten (loggingBehavior "production") zet
 * ook Capacitor's eigen regels aan, en die bevatten de ruwe invoer van élke plugin-aanroep — daar
 * staat het sessietoken in. Deze weg logt alleen wat hieronder is klaargemaakt, en verder niets.
 *
 * Wat er met opzet niet in komt: het sessietoken, wachtwoorden, en de onafgeronde coördinaten. Een
 * logregel is een kopie die blijft liggen, en van een toegangsbewijs is alleen interessant óf het
 * er was en hoe lang het is. Wie een precieze locatie in een logboek zet, heeft haar alsnog
 * opgeschreven.
 */
const GEHEIM = /^(token|password|wachtwoord|authorization|apikey)$/i;

/* Een geheim wordt zijn lengte: genoeg om te zien of het er was, te weinig om het te gebruiken */
const verkort = (v) => (typeof v === "string" && v !== "" ? `<${v.length} tekens>` : "<leeg>");

/* Waarden klaarmaken om te tonen; geheime velden worden vervangen, de rest gaat zoals hij is */
const schoon = (waarde) => {
  if (waarde === null || typeof waarde !== "object") return waarde;
  if (Array.isArray(waarde)) return waarde.map(schoon);
  return Object.fromEntries(
    Object.entries(waarde).map(([k, v]) => [k, GEHEIM.test(k) ? verkort(v) : schoon(v)])
  );
};

/* Naar één regel, want logcat knipt op regels. Onleesbaar (cyclisch) mag nooit de app breken. */
export const toon = (waarde) => {
  if (waarde === undefined) return "undefined";
  try {
    return JSON.stringify(schoon(waarde));
  } catch {
    return String(waarde);
  }
};

/*
 * Een regel wegschrijven mag nooit iets kapotmaken: het logboek is er om een storing te kunnen
 * zien, niet om er zelf een te worden. Vandaar de vangnetten en het bewust niet afwachten van de
 * plugin — logregels horen niet in de weg te lopen van waar de gebruiker op wacht.
 */
export const log = (...delen) => {
  const regel = delen.map((d) => (typeof d === "string" ? d : toon(d))).join(" ");
  if (Postbode) {
    try {
      Postbode.log({ regel }).catch(() => {});
    } catch {
      /* een app-versie die deze methode nog niet kent: dan geen regel, en verder niets aan de hand */
    }
  } else {
    console.log("[liefdesbrieven]", regel); // de browser tijdens het ontwikkelen
  }
};

/*
 * Eén aanroep mét zijn antwoord. Beide kanten komen in het log: wat erin ging en wat eruit kwam —
 * of de afwijzing, en dan vooral de `code`, want daar zet een Capacitor-plugin de eigenlijke reden
 * in ("location-disabled", "location-timeout", …). De boodschap alleen is te vaag om iets aan te
 * hebben.
 */
export async function gelogd(naam, invoer, fn) {
  log(`→ ${naam}`, toon(invoer));
  try {
    const uit = await fn();
    log(`← ${naam}`, toon(uit));
    return uit;
  } catch (e) {
    log(`✗ ${naam}`, toon({ code: e?.code ?? null, message: e?.message ?? String(e) }));
    throw e;
  }
}