{
  "version": 3,
  "sources": ["pwa_client_version.js"],
  "sourcesContent": ["/*\n * static/js/pwa_client_version.js \u2014 Stamp X-Client-Version on same-origin\n * client requests (SNOW-388).\n *\n * Four server-side ``emit_server_signal`` call sites (five signals \u2014 push\n * emits both ``.sent`` and ``.gone_410`` from one call site)\n * (``public/api.py::version``, ``public/api.py::sw_config``,\n * ``accounts/push_views.py::push_test``,\n * ``core/idempotency.py::IdempotencyMiddleware``) read ``client_version``\n * from the ``X-Client-Version`` request header. Until this script, no\n * client sent it, so the property landed in PostHog as ``\"\"``. This file\n * is the client-side half: it stamps the header on every same-origin\n * request the page issues, whether via ``fetch`` or HTMX.\n *\n * ONE CENTRAL WRAPPER, NOT ~25 CALL-SITE EDITS. The frontend makes\n * same-origin ``fetch()`` calls from ``sw_register.js``, ``telemetry.js``,\n * ``map.js``, ``map_edit_resorts.js``, ``push_demo.js``, ``passkey.js``,\n * and every HTMX-driven partial swap. Editing each call site individually\n * would be repetitive and easy to miss on new additions \u2014 a single\n * monkey-patch plus one HTMX listener covers all of them.\n *\n * LOAD ORDER IS LOAD-BEARING \u2014 THIS SCRIPT MUST LOAD FIRST (right after\n * ``db.js``, before ``sw_register.js``, ``telemetry.js``,\n * ``mutation_queue.js``, ``pwa_version_check.js``, and ``pwa_offline.js``).\n *\n * ``sw_register.js`` dispatches a ``fetch('/api/sw-config')`` SYNCHRONOUSLY\n * at its own IIFE-load (``fetchSwConfig()``, called immediately, not from\n * an event handler) \u2014 there is no user interaction or async tick between\n * script-parse and that call. Whichever wrapper is installed on\n * ``window.fetch`` at that moment is the one this pre-register fetch goes\n * through; any wrapper installed AFTER ``sw_register.js`` has executed\n * simply never sees it, so this script must have patched ``window.fetch``\n * before that script's script tag runs.\n *\n * Because each wrapper captures ``window.fetch`` at the time it runs and\n * reassigns ``window.fetch`` to its own version, the FIRST script to\n * install a wrapper becomes the INNERMOST one \u2014 the last to see a\n * caller's request before it reaches the native ``fetch``, and the first\n * to see the real response on the way back out. Loading first therefore\n * means every later wrapper's calls to \"the current ``window.fetch``\"\n * resolve, through the composed chain, down to this one \u2014 so our header\n * injection still runs on every request, including those issued by\n * scripts that load after us.\n *\n * This composition is only safe because ``pwa_offline.js`` and\n * ``pwa_version_check.js`` (both of which patch ``window.fetch`` after\n * this script) are PURE RESPONSE-SIDE OBSERVERS \u2014 they read response\n * headers and rethrow/return the response unchanged; neither reads nor\n * mutates the outbound request or its headers. If a future script needs\n * to mutate the outbound request (add/remove a header, rewrite the URL),\n * it must load BEFORE this one, or it will silently lose to whatever\n * ``fetch(..)`` call this wrapper already dispatched downstream. Do not\n * reorder without re-reading this comment and re-auditing every wrapper\n * between ``db.js`` and this script's tag in\n * ``public/templates/public/base.html``.\n *\n * SCOPE \u2014 deliberately excluded:\n *   * Service-worker-side fetch wrapping (``sw.js``) \u2014 every signal this\n *     ticket targets fires from a JS-initiated request already covered\n *     by this page-side wrapper; ``sw.js`` passes ``event.request``\n *     through unchanged, so headers set here survive into the network\n *     unmodified.\n *   * ``navigator.sendBeacon`` \u2014 cannot carry custom headers by design.\n *     ``telemetry.js``'s critical-event beacon path already carries\n *     ``client_version`` inside the envelope body instead.\n *   * Third-party requests (MapLibre tile/style URLs, basemap fetches) \u2014\n *     filtered out by the same-origin check below.\n *\n * Public surface: none. This is a side-effecting IIFE, matching\n * ``pwa_offline.js`` / ``pwa_version_check.js``.\n */\n\n(function () {\n  'use strict';\n\n  const HEADER = 'X-Client-Version';\n\n  const CLIENT_VERSION = (() => {\n    const el = document.querySelector('meta[name=\"pwa-app-version\"]');\n    return el ? (el.getAttribute('content') || '').trim() : '';\n  })();\n\n  // No version baked into the shell (stale template, or the meta tag was\n  // removed) \u2014 nothing meaningful to add. Matches the fail-safe pattern\n  // in pwa_version_check.js's own meta-tag guard.\n  if (!CLIENT_VERSION) return;\n\n  /**\n   * True when ``url`` resolves to the same origin as the current page.\n   * Relative URLs (the common case \u2014 HTMX paths, same-origin fetches)\n   * always pass; a malformed absolute URL fails closed (treated as\n   * cross-origin, so it is left untouched).\n   *\n   * @param {string} url\n   * @returns {boolean}\n   */\n  function isSameOrigin(url) {\n    try {\n      return new URL(url, location.href).origin === location.origin;\n    } catch (_err) {\n      return false;\n    }\n  }\n\n  /**\n   * Wrap ``window.fetch`` so every same-origin call carries\n   * ``X-Client-Version``. Handles both call shapes \u2014 ``fetch(url, init)``\n   * and ``fetch(request)`` \u2014 without clobbering a header a caller already\n   * set explicitly. ``Request.headers`` is immutable, so the ``Request``\n   * shape is rebuilt via ``new Request(orig, { headers })`` rather than\n   * mutated in place.\n   */\n  function wrapFetch() {\n    if (typeof window.fetch !== 'function') return;\n    const nativeFetch = window.fetch.bind(window);\n    window.fetch = function (resource, init) {\n      if (resource instanceof Request) {\n        if (isSameOrigin(resource.url) && !resource.headers.has(HEADER)) {\n          const headers = new Headers(resource.headers);\n          headers.set(HEADER, CLIENT_VERSION);\n          // Assumption: no Snowdesk call site does fetch(requestObj, init)\n          // with its own init.headers \u2014 per the fetch spec, a second-arg\n          // init.headers would take priority over the rebuilt Request's\n          // headers and silently drop our injection. Revisit if that shape\n          // is ever introduced.\n          return nativeFetch(new Request(resource, { headers }), init);\n        }\n        return nativeFetch(resource, init);\n      }\n      if (isSameOrigin(resource)) {\n        const headers = new Headers((init && init.headers) || {});\n        if (!headers.has(HEADER)) headers.set(HEADER, CLIENT_VERSION);\n        return nativeFetch(resource, Object.assign({}, init, { headers }));\n      }\n      return nativeFetch(resource, init);\n    };\n  }\n\n  /**\n   * Stamp same-origin HTMX requests via ``htmx:configRequest`` \u2014 HTMX\n   * issues its own ``XMLHttpRequest`` rather than calling ``fetch``, so\n   * the wrapper above never sees these.\n   *\n   * @param {CustomEvent} evt\n   */\n  function onHtmxConfigRequest(evt) {\n    const path = evt.detail && evt.detail.path;\n    if (!path || !isSameOrigin(path)) return;\n    if (!evt.detail.headers[HEADER]) evt.detail.headers[HEADER] = CLIENT_VERSION;\n  }\n\n  wrapFetch();\n  document.body?.addEventListener('htmx:configRequest', onHtmxConfigRequest);\n})();\n"],
  "mappings": "CAwEC,UAAY,CACX,aAEA,MAAMA,EAAS,mBAETC,GAAkB,IAAM,CAC5B,MAAMC,EAAK,SAAS,cAAc,8BAA8B,EAChE,OAAOA,GAAMA,EAAG,aAAa,SAAS,GAAK,IAAI,KAAK,EAAI,EAC1D,GAAG,EAKH,GAAI,CAACD,EAAgB,OAWrB,SAASE,EAAaC,EAAK,CACzB,GAAI,CACF,OAAO,IAAI,IAAIA,EAAK,SAAS,IAAI,EAAE,SAAW,SAAS,MACzD,MAAe,CACb,MAAO,EACT,CACF,CAUA,SAASC,GAAY,CACnB,GAAI,OAAO,OAAO,OAAU,WAAY,OACxC,MAAMC,EAAc,OAAO,MAAM,KAAK,MAAM,EAC5C,OAAO,MAAQ,SAAUC,EAAUC,EAAM,CACvC,GAAID,aAAoB,QAAS,CAC/B,GAAIJ,EAAaI,EAAS,GAAG,GAAK,CAACA,EAAS,QAAQ,IAAIP,CAAM,EAAG,CAC/D,MAAMS,EAAU,IAAI,QAAQF,EAAS,OAAO,EAC5C,OAAAE,EAAQ,IAAIT,EAAQC,CAAc,EAM3BK,EAAY,IAAI,QAAQC,EAAU,CAAE,QAAAE,CAAQ,CAAC,EAAGD,CAAI,CAC7D,CACA,OAAOF,EAAYC,EAAUC,CAAI,CACnC,CACA,GAAIL,EAAaI,CAAQ,EAAG,CAC1B,MAAME,EAAU,IAAI,QAASD,GAAQA,EAAK,SAAY,CAAC,CAAC,EACxD,OAAKC,EAAQ,IAAIT,CAAM,GAAGS,EAAQ,IAAIT,EAAQC,CAAc,EACrDK,EAAYC,EAAU,OAAO,OAAO,CAAC,EAAGC,EAAM,CAAE,QAAAC,CAAQ,CAAC,CAAC,CACnE,CACA,OAAOH,EAAYC,EAAUC,CAAI,CACnC,CACF,CASA,SAASE,EAAoBC,EAAK,CAChC,MAAMC,EAAOD,EAAI,QAAUA,EAAI,OAAO,KAClC,CAACC,GAAQ,CAACT,EAAaS,CAAI,GAC1BD,EAAI,OAAO,QAAQX,CAAM,IAAGW,EAAI,OAAO,QAAQX,CAAM,EAAIC,EAChE,CAEAI,EAAU,EACV,SAAS,MAAM,iBAAiB,qBAAsBK,CAAmB,CAC3E,GAAG",
  "names": ["HEADER", "CLIENT_VERSION", "el", "isSameOrigin", "url", "wrapFetch", "nativeFetch", "resource", "init", "headers", "onHtmxConfigRequest", "evt", "path"]
}
