termbeam 1.20.3 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +630 -0
  2. package/package.json +3 -2
  3. package/public/assets/{_basePickBy-BLefhu0l.js → _basePickBy-BIHCnP-C.js} +1 -1
  4. package/public/assets/{_baseUniq-DaY_Bc3O.js → _baseUniq-DnMFuvsx.js} +1 -1
  5. package/public/assets/{arc-DmuNthMW.js → arc-BNbndmGK.js} +1 -1
  6. package/public/assets/{architectureDiagram-Q4EWVU46-D_3Wy2pQ.js → architectureDiagram-Q4EWVU46-BmFTw0nZ.js} +1 -1
  7. package/public/assets/{blockDiagram-DXYQGD6D-BcStipzf.js → blockDiagram-DXYQGD6D-wN2o-9_g.js} +1 -1
  8. package/public/assets/{c4Diagram-AHTNJAMY-BwE7ZnCD.js → c4Diagram-AHTNJAMY-BYDCN8H0.js} +1 -1
  9. package/public/assets/channel-DSjdyO61.js +1 -0
  10. package/public/assets/{chunk-4BX2VUAB-CxYOWomN.js → chunk-4BX2VUAB-Cob7CgE_.js} +1 -1
  11. package/public/assets/{chunk-4TB4RGXK-D1SjwnL0.js → chunk-4TB4RGXK-DDonZyK6.js} +1 -1
  12. package/public/assets/{chunk-55IACEB6-CCtV1y23.js → chunk-55IACEB6-BTW1fQoW.js} +1 -1
  13. package/public/assets/{chunk-EDXVE4YY-CwJdMkPT.js → chunk-EDXVE4YY-BgWTXLsq.js} +1 -1
  14. package/public/assets/{chunk-FMBD7UC4-CL6X-Bgf.js → chunk-FMBD7UC4-CxmTHyai.js} +1 -1
  15. package/public/assets/{chunk-OYMX7WX6-Nt-YAKKo.js → chunk-OYMX7WX6-v5mXWXoC.js} +1 -1
  16. package/public/assets/{chunk-QZHKN3VN-JqEPJ-I8.js → chunk-QZHKN3VN-CyNtEZcY.js} +1 -1
  17. package/public/assets/{chunk-YZCP3GAM-B2BkSOHZ.js → chunk-YZCP3GAM-qiJvjghT.js} +1 -1
  18. package/public/assets/classDiagram-6PBFFD2Q-DRtX5Ta8.js +1 -0
  19. package/public/assets/classDiagram-v2-HSJHXN6E-DRtX5Ta8.js +1 -0
  20. package/public/assets/clone-iFtwY3RV.js +1 -0
  21. package/public/assets/{cose-bilkent-S5V4N54A-B2XXKALr.js → cose-bilkent-S5V4N54A-CsbF4Rbc.js} +1 -1
  22. package/public/assets/{dagre-KV5264BT-BbosVmxG.js → dagre-KV5264BT-CiBddJE9.js} +1 -1
  23. package/public/assets/{diagram-5BDNPKRD-DwScs67g.js → diagram-5BDNPKRD-4Km3IxIT.js} +1 -1
  24. package/public/assets/{diagram-G4DWMVQ6--1gv_wcM.js → diagram-G4DWMVQ6-DD5Ucpcn.js} +1 -1
  25. package/public/assets/{diagram-MMDJMWI5-C1yHkOFA.js → diagram-MMDJMWI5-B6-WK_TJ.js} +1 -1
  26. package/public/assets/{diagram-TYMM5635-Dl7dRWkC.js → diagram-TYMM5635-CLYhOm9a.js} +1 -1
  27. package/public/assets/{erDiagram-SMLLAGMA-DLmNKAuD.js → erDiagram-SMLLAGMA-DgukEqTQ.js} +1 -1
  28. package/public/assets/{flowDiagram-DWJPFMVM-CZa_uY2_.js → flowDiagram-DWJPFMVM-DUlTxDrh.js} +1 -1
  29. package/public/assets/{ganttDiagram-T4ZO3ILL-BnT7GCzh.js → ganttDiagram-T4ZO3ILL-D5Ik9clK.js} +1 -1
  30. package/public/assets/{gitGraphDiagram-UUTBAWPF-D0of7G0H.js → gitGraphDiagram-UUTBAWPF-CouNbB0H.js} +1 -1
  31. package/public/assets/{graph-DQMLsVKn.js → graph-DY36UTy7.js} +1 -1
  32. package/public/assets/index-CwjgIG7M.js +463 -0
  33. package/public/assets/index-DWaSRzf6.css +32 -0
  34. package/public/assets/{infoDiagram-42DDH7IO-CCYTG5TW.js → infoDiagram-42DDH7IO-CTZf-XaE.js} +1 -1
  35. package/public/assets/{ishikawaDiagram-UXIWVN3A-6aQrUmM1.js → ishikawaDiagram-UXIWVN3A-DZdSiihk.js} +1 -1
  36. package/public/assets/{journeyDiagram-VCZTEJTY-CJTv8kT4.js → journeyDiagram-VCZTEJTY-Cx-gOesl.js} +1 -1
  37. package/public/assets/{kanban-definition-6JOO6SKY-BcvXQPfh.js → kanban-definition-6JOO6SKY-NjVvkzyg.js} +1 -1
  38. package/public/assets/{layout-ThSqQjtq.js → layout-Bcu4s7Ho.js} +1 -1
  39. package/public/assets/{linear-DCFOEcB6.js → linear-s0Mg7155.js} +1 -1
  40. package/public/assets/{mindmap-definition-QFDTVHPH-Bb4AuZN4.js → mindmap-definition-QFDTVHPH-DQUtHqQ6.js} +1 -1
  41. package/public/assets/{pieDiagram-DEJITSTG-DQqclfI2.js → pieDiagram-DEJITSTG-DlYgVpVr.js} +1 -1
  42. package/public/assets/{quadrantDiagram-34T5L4WZ-pb0aN3QY.js → quadrantDiagram-34T5L4WZ-DloaxY2h.js} +1 -1
  43. package/public/assets/{requirementDiagram-MS252O5E-CkL3sbnK.js → requirementDiagram-MS252O5E-fSM1Pi3V.js} +1 -1
  44. package/public/assets/{sankeyDiagram-XADWPNL6-CP6XoGCk.js → sankeyDiagram-XADWPNL6-BHPnOiHK.js} +1 -1
  45. package/public/assets/{sequenceDiagram-FGHM5R23-CoFyaUFj.js → sequenceDiagram-FGHM5R23-Dnl-W6jS.js} +1 -1
  46. package/public/assets/{stateDiagram-FHFEXIEX-WQkLynRi.js → stateDiagram-FHFEXIEX-X9kal6wR.js} +1 -1
  47. package/public/assets/stateDiagram-v2-QKLJ7IA2-C7M79J7F.js +1 -0
  48. package/public/assets/{timeline-definition-GMOUNBTQ-Dcb9ue8q.js → timeline-definition-GMOUNBTQ-C3o7gZFF.js} +1 -1
  49. package/public/assets/{vennDiagram-DHZGUBPP-KqcKNQ1-.js → vennDiagram-DHZGUBPP-DoHPigKa.js} +1 -1
  50. package/public/assets/{wardley-RL74JXVD-DmgKZSUh.js → wardley-RL74JXVD-BEjx3hAD.js} +1 -1
  51. package/public/assets/{wardleyDiagram-NUSXRM2D-4y-iyT2D.js → wardleyDiagram-NUSXRM2D-Dsy9JWUf.js} +1 -1
  52. package/public/assets/{xychartDiagram-5P7HB3ND-Bdcd_98G.js → xychartDiagram-5P7HB3ND-cd-6HXrN.js} +1 -1
  53. package/public/index.html +3 -3
  54. package/public/sw.js +1 -1
  55. package/src/server/routes.js +31 -0
  56. package/src/tunnel/index.js +130 -4
  57. package/public/assets/channel-Bz1ES3Md.js +0 -1
  58. package/public/assets/classDiagram-6PBFFD2Q-C0Xsg2c2.js +0 -1
  59. package/public/assets/classDiagram-v2-HSJHXN6E-C0Xsg2c2.js +0 -1
  60. package/public/assets/clone-DTHql6BK.js +0 -1
  61. package/public/assets/index-Bp7KnjkK.js +0 -455
  62. package/public/assets/index-KBnPi8DC.css +0 -32
  63. package/public/assets/stateDiagram-v2-QKLJ7IA2-D1F0xws2.js +0 -1
package/public/sw.js CHANGED
@@ -1,2 +1,2 @@
1
1
  try{self["workbox:core:7.3.0"]&&_()}catch{}const G=(s,...e)=>{let t=s;return e.length>0&&(t+=` :: ${JSON.stringify(e)}`),t},Q=G;class h extends Error{constructor(e,t){const n=Q(e,t);super(n),this.name=e,this.details=t}}const d={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:typeof registration<"u"?registration.scope:""},E=s=>[d.prefix,s,d.suffix].filter(e=>e&&e.length>0).join("-"),z=s=>{for(const e of Object.keys(d))s(e)},b={updateDetails:s=>{z(e=>{typeof s[e]=="string"&&(d[e]=s[e])})},getGoogleAnalyticsName:s=>s||E(d.googleAnalytics),getPrecacheName:s=>s||E(d.precache),getPrefix:()=>d.prefix,getRuntimeName:s=>s||E(d.runtime),getSuffix:()=>d.suffix};function v(s,e){const t=e();return s.waitUntil(t),t}try{self["workbox:precaching:7.3.0"]&&_()}catch{}const J="__WB_REVISION__";function X(s){if(!s)throw new h("add-to-cache-list-unexpected-type",{entry:s});if(typeof s=="string"){const i=new URL(s,location.href);return{cacheKey:i.href,url:i.href}}const{revision:e,url:t}=s;if(!t)throw new h("add-to-cache-list-unexpected-type",{entry:s});if(!e){const i=new URL(t,location.href);return{cacheKey:i.href,url:i.href}}const n=new URL(t,location.href),a=new URL(t,location.href);return n.searchParams.set(J,e),{cacheKey:n.href,url:a.href}}class Y{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type==="install"&&t&&t.originalRequest&&t.originalRequest instanceof Request){const a=t.originalRequest.url;n?this.notUpdatedURLs.push(a):this.updatedURLs.push(a)}return n}}}class Z{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:t,params:n})=>{const a=(n==null?void 0:n.cacheKey)||this._precacheController.getCacheKeyForURL(t.url);return a?new Request(a,{headers:t.headers}):t},this._precacheController=e}}let m;function ee(){if(m===void 0){const s=new Response("");if("body"in s)try{new Response(s.body),m=!0}catch{m=!1}m=!1}return m}async function te(s,e){let t=null;if(s.url&&(t=new URL(s.url).origin),t!==self.location.origin)throw new h("cross-origin-copy-response",{origin:t});const n=s.clone(),i={headers:new Headers(n.headers),status:n.status,statusText:n.statusText},r=ee()?n.body:await n.blob();return new Response(r,i)}const se=s=>new URL(String(s),location.href).href.replace(new RegExp(`^${location.origin}`),"");function M(s,e){const t=new URL(s);for(const n of e)t.searchParams.delete(n);return t.href}async function ne(s,e,t,n){const a=M(e.url,t);if(e.url===a)return s.match(e,n);const i=Object.assign(Object.assign({},n),{ignoreSearch:!0}),r=await s.keys(e,i);for(const c of r){const o=M(c.url,t);if(a===o)return s.match(c,n)}}class ae{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}}const B=new Set;async function ie(){for(const s of B)await s()}function re(s){return new Promise(e=>setTimeout(e,s))}try{self["workbox:strategies:7.3.0"]&&_()}catch{}function C(s){return typeof s=="string"?new Request(s):s}class ce{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new ae,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(const n of this._plugins)this._pluginStateMap.set(n,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){const{event:t}=this;let n=C(e);if(n.mode==="navigate"&&t instanceof FetchEvent&&t.preloadResponse){const r=await t.preloadResponse;if(r)return r}const a=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const r of this.iterateCallbacks("requestWillFetch"))n=await r({request:n.clone(),event:t})}catch(r){if(r instanceof Error)throw new h("plugin-error-request-will-fetch",{thrownErrorMessage:r.message})}const i=n.clone();try{let r;r=await fetch(n,n.mode==="navigate"?void 0:this._strategy.fetchOptions);for(const c of this.iterateCallbacks("fetchDidSucceed"))r=await c({event:t,request:i,response:r});return r}catch(r){throw a&&await this.runCallbacks("fetchDidFail",{error:r,event:t,originalRequest:a.clone(),request:i.clone()}),r}}async fetchAndCachePut(e){const t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){const t=C(e);let n;const{cacheName:a,matchOptions:i}=this._strategy,r=await this.getCacheKey(t,"read"),c=Object.assign(Object.assign({},i),{cacheName:a});n=await caches.match(r,c);for(const o of this.iterateCallbacks("cachedResponseWillBeUsed"))n=await o({cacheName:a,matchOptions:i,cachedResponse:n,request:r,event:this.event})||void 0;return n}async cachePut(e,t){const n=C(e);await re(0);const a=await this.getCacheKey(n,"write");if(!t)throw new h("cache-put-with-no-response",{url:se(a.url)});const i=await this._ensureResponseSafeToCache(t);if(!i)return!1;const{cacheName:r,matchOptions:c}=this._strategy,o=await self.caches.open(r),l=this.hasCallback("cacheDidUpdate"),g=l?await ne(o,a.clone(),["__WB_REVISION__"],c):null;try{await o.put(a,l?i.clone():i)}catch(u){if(u instanceof Error)throw u.name==="QuotaExceededError"&&await ie(),u}for(const u of this.iterateCallbacks("cacheDidUpdate"))await u({cacheName:r,oldResponse:g,newResponse:i.clone(),request:a,event:this.event});return!0}async getCacheKey(e,t){const n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let a=e;for(const i of this.iterateCallbacks("cacheKeyWillBeUsed"))a=C(await i({mode:t,request:a,event:this.event,params:this.params}));this._cacheKeys[n]=a}return this._cacheKeys[n]}hasCallback(e){for(const t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(const n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(const t of this._strategy.plugins)if(typeof t[e]=="function"){const n=this._pluginStateMap.get(t);yield i=>{const r=Object.assign(Object.assign({},i),{state:n});return t[e](r)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){const e=this._extendLifetimePromises.splice(0),n=(await Promise.allSettled(e)).find(a=>a.status==="rejected");if(n)throw n.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(const a of this.iterateCallbacks("cacheWillUpdate"))if(t=await a({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}}class W{constructor(e={}){this.cacheName=b.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){const[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});const t=e.event,n=typeof e.request=="string"?new Request(e.request):e.request,a="params"in e?e.params:void 0,i=new ce(this,{event:t,request:n,params:a}),r=this._getResponse(i,n,t),c=this._awaitComplete(r,i,n,t);return[r,c]}async _getResponse(e,t,n){await e.runCallbacks("handlerWillStart",{event:n,request:t});let a;try{if(a=await this._handle(t,e),!a||a.type==="error")throw new h("no-response",{url:t.url})}catch(i){if(i instanceof Error){for(const r of e.iterateCallbacks("handlerDidError"))if(a=await r({error:i,event:n,request:t}),a)break}if(!a)throw i}for(const i of e.iterateCallbacks("handlerWillRespond"))a=await i({event:n,request:t,response:a});return a}async _awaitComplete(e,t,n,a){let i,r;try{i=await e}catch{}try{await t.runCallbacks("handlerDidRespond",{event:a,request:n,response:i}),await t.doneWaiting()}catch(c){c instanceof Error&&(r=c)}if(await t.runCallbacks("handlerDidComplete",{event:a,request:n,response:i,error:r}),t.destroy(),r)throw r}}class p extends W{constructor(e={}){e.cacheName=b.getPrecacheName(e.cacheName),super(e),this._fallbackToNetwork=e.fallbackToNetwork!==!1,this.plugins.push(p.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){const n=await t.cacheMatch(e);return n||(t.event&&t.event.type==="install"?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,t){let n;const a=t.params||{};if(this._fallbackToNetwork){const i=a.integrity,r=e.integrity,c=!r||r===i;n=await t.fetch(new Request(e,{integrity:e.mode!=="no-cors"?r||i:void 0})),i&&c&&e.mode!=="no-cors"&&(this._useDefaultCacheabilityPluginIfNeeded(),await t.cachePut(e,n.clone()))}else throw new h("missing-precache-entry",{cacheName:this.cacheName,url:e.url});return n}async _handleInstall(e,t){this._useDefaultCacheabilityPluginIfNeeded();const n=await t.fetch(e);if(!await t.cachePut(e,n.clone()))throw new h("bad-precaching-response",{url:e.url,status:n.status});return n}_useDefaultCacheabilityPluginIfNeeded(){let e=null,t=0;for(const[n,a]of this.plugins.entries())a!==p.copyRedirectedCacheableResponsesPlugin&&(a===p.defaultPrecacheCacheabilityPlugin&&(e=n),a.cacheWillUpdate&&t++);t===0?this.plugins.push(p.defaultPrecacheCacheabilityPlugin):t>1&&e!==null&&this.plugins.splice(e,1)}}p.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:s}){return!s||s.status>=400?null:s}};p.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:s}){return s.redirected?await te(s):s}};class oe{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new p({cacheName:b.getPrecacheName(e),plugins:[...t,new Z({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this._installAndActiveListenersAdded=!0)}addToCacheList(e){const t=[];for(const n of e){typeof n=="string"?t.push(n):n&&n.revision===void 0&&t.push(n.url);const{cacheKey:a,url:i}=X(n),r=typeof n!="string"&&n.revision?"reload":"default";if(this._urlsToCacheKeys.has(i)&&this._urlsToCacheKeys.get(i)!==a)throw new h("add-to-cache-list-conflicting-entries",{firstEntry:this._urlsToCacheKeys.get(i),secondEntry:a});if(typeof n!="string"&&n.integrity){if(this._cacheKeysToIntegrities.has(a)&&this._cacheKeysToIntegrities.get(a)!==n.integrity)throw new h("add-to-cache-list-conflicting-integrities",{url:i});this._cacheKeysToIntegrities.set(a,n.integrity)}if(this._urlsToCacheKeys.set(i,a),this._urlsToCacheModes.set(i,r),t.length>0){const c=`Workbox is precaching URLs without revision info: ${t.join(", ")}
2
- This is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(c)}}}install(e){return v(e,async()=>{const t=new Y;this.strategy.plugins.push(t);for(const[i,r]of this._urlsToCacheKeys){const c=this._cacheKeysToIntegrities.get(r),o=this._urlsToCacheModes.get(i),l=new Request(i,{integrity:c,cache:o,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:r},request:l,event:e}))}const{updatedURLs:n,notUpdatedURLs:a}=t;return{updatedURLs:n,notUpdatedURLs:a}})}activate(e){return v(e,async()=>{const t=await self.caches.open(this.strategy.cacheName),n=await t.keys(),a=new Set(this._urlsToCacheKeys.values()),i=[];for(const r of n)a.has(r.url)||(await t.delete(r),i.push(r.url));return{deletedURLs:i}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){const t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){const t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){const t=this.getCacheKeyForURL(e);if(!t)throw new h("non-precached-url",{url:e});return n=>(n.request=new Request(e),n.params=Object.assign({cacheKey:t},n.params),this.strategy.handle(n))}}let D;const j=()=>(D||(D=new oe),D);try{self["workbox:routing:7.3.0"]&&_()}catch{}const F="GET",x=s=>s&&typeof s=="object"?s:{handle:s};class R{constructor(e,t,n=F){this.handler=x(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=x(e)}}class le extends R{constructor(e,t,n){const a=({url:i})=>{const r=e.exec(i.href);if(r&&!(i.origin!==location.origin&&r.index!==0))return r.slice(1)};super(a,t,n)}}class he{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",(e=>{const{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener("message",(e=>{if(e.data&&e.data.type==="CACHE_URLS"){const{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(a=>{typeof a=="string"&&(a=[a]);const i=new Request(...a);return this.handleRequest({request:i,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){const n=new URL(e.url,location.href);if(!n.protocol.startsWith("http"))return;const a=n.origin===location.origin,{params:i,route:r}=this.findMatchingRoute({event:t,request:e,sameOrigin:a,url:n});let c=r&&r.handler;const o=e.method;if(!c&&this._defaultHandlerMap.has(o)&&(c=this._defaultHandlerMap.get(o)),!c)return;let l;try{l=c.handle({url:n,request:e,event:t,params:i})}catch(u){l=Promise.reject(u)}const g=r&&r.catchHandler;return l instanceof Promise&&(this._catchHandler||g)&&(l=l.catch(async u=>{if(g)try{return await g.handle({url:n,request:e,event:t,params:i})}catch(N){N instanceof Error&&(u=N)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw u})),l}findMatchingRoute({url:e,sameOrigin:t,request:n,event:a}){const i=this._routes.get(n.method)||[];for(const r of i){let c;const o=r.match({url:e,sameOrigin:t,request:n,event:a});if(o)return c=o,(Array.isArray(c)&&c.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o=="boolean")&&(c=void 0),{route:r,params:c}}return{}}setDefaultHandler(e,t=F){this._defaultHandlerMap.set(t,x(e))}setCatchHandler(e){this._catchHandler=x(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new h("unregister-route-but-not-found-with-method",{method:e.method});const t=this._routes.get(e.method).indexOf(e);if(t>-1)this._routes.get(e.method).splice(t,1);else throw new h("unregister-route-route-not-registered")}}let y;const ue=()=>(y||(y=new he,y.addFetchListener(),y.addCacheListener()),y);function q(s,e,t){let n;if(typeof s=="string"){const i=new URL(s,location.href),r=({url:c})=>c.href===i.href;n=new R(r,e,t)}else if(s instanceof RegExp)n=new le(s,e,t);else if(typeof s=="function")n=new R(s,e,t);else if(s instanceof R)n=s;else throw new h("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});return ue().registerRoute(n),n}function de(s,e=[]){for(const t of[...s.searchParams.keys()])e.some(n=>n.test(t))&&s.searchParams.delete(t);return s}function*fe(s,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:t="index.html",cleanURLs:n=!0,urlManipulation:a}={}){const i=new URL(s,location.href);i.hash="",yield i.href;const r=de(i,e);if(yield r.href,t&&r.pathname.endsWith("/")){const c=new URL(r.href);c.pathname+=t,yield c.href}if(n){const c=new URL(r.href);c.pathname+=".html",yield c.href}if(a){const c=a({url:i});for(const o of c)yield o.href}}class pe extends R{constructor(e,t){const n=({request:a})=>{const i=e.getURLsToCacheKeys();for(const r of fe(a.url,t)){const c=i.get(r);if(c){const o=e.getIntegrityForCacheKey(c);return{cacheKey:c,integrity:o}}}};super(n,e.strategy)}}function ge(s){const e=j(),t=new pe(e,s);q(t)}const me="-precache-",ye=async(s,e=me)=>{const n=(await self.caches.keys()).filter(a=>a.includes(e)&&a.includes(self.registration.scope)&&a!==s);return await Promise.all(n.map(a=>self.caches.delete(a))),n};function we(){self.addEventListener("activate",(s=>{const e=b.getPrecacheName();s.waitUntil(ye(e).then(t=>{}))}))}function _e(s){j().precache(s)}function Re(s,e){_e(s),ge(e)}class be extends W{async _handle(e,t){let n=await t.cacheMatch(e),a;if(!n)try{n=await t.fetchAndCachePut(e)}catch(i){i instanceof Error&&(a=i)}if(!n)throw new h("no-response",{url:e.url,error:a});return n}}function H(s){s.then(()=>{})}const Ce=(s,e)=>e.some(t=>s instanceof t);let A,K;function xe(){return A||(A=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function Ee(){return K||(K=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const V=new WeakMap,k=new WeakMap,$=new WeakMap,L=new WeakMap,P=new WeakMap;function De(s){const e=new Promise((t,n)=>{const a=()=>{s.removeEventListener("success",i),s.removeEventListener("error",r)},i=()=>{t(f(s.result)),a()},r=()=>{n(s.error),a()};s.addEventListener("success",i),s.addEventListener("error",r)});return e.then(t=>{t instanceof IDBCursor&&V.set(t,s)}).catch(()=>{}),P.set(e,s),e}function Le(s){if(k.has(s))return;const e=new Promise((t,n)=>{const a=()=>{s.removeEventListener("complete",i),s.removeEventListener("error",r),s.removeEventListener("abort",r)},i=()=>{t(),a()},r=()=>{n(s.error||new DOMException("AbortError","AbortError")),a()};s.addEventListener("complete",i),s.addEventListener("error",r),s.addEventListener("abort",r)});k.set(s,e)}let I={get(s,e,t){if(s instanceof IDBTransaction){if(e==="done")return k.get(s);if(e==="objectStoreNames")return s.objectStoreNames||$.get(s);if(e==="store")return t.objectStoreNames[1]?void 0:t.objectStore(t.objectStoreNames[0])}return f(s[e])},set(s,e,t){return s[e]=t,!0},has(s,e){return s instanceof IDBTransaction&&(e==="done"||e==="store")?!0:e in s}};function Ue(s){I=s(I)}function Te(s){return s===IDBDatabase.prototype.transaction&&!("objectStoreNames"in IDBTransaction.prototype)?function(e,...t){const n=s.call(U(this),e,...t);return $.set(n,e.sort?e.sort():[e]),f(n)}:Ee().includes(s)?function(...e){return s.apply(U(this),e),f(V.get(this))}:function(...e){return f(s.apply(U(this),e))}}function ke(s){return typeof s=="function"?Te(s):(s instanceof IDBTransaction&&Le(s),Ce(s,xe())?new Proxy(s,I):s)}function f(s){if(s instanceof IDBRequest)return De(s);if(L.has(s))return L.get(s);const e=ke(s);return e!==s&&(L.set(s,e),P.set(e,s)),e}const U=s=>P.get(s);function Ie(s,e,{blocked:t,upgrade:n,blocking:a,terminated:i}={}){const r=indexedDB.open(s,e),c=f(r);return n&&r.addEventListener("upgradeneeded",o=>{n(f(r.result),o.oldVersion,o.newVersion,f(r.transaction),o)}),t&&r.addEventListener("blocked",o=>t(o.oldVersion,o.newVersion,o)),c.then(o=>{i&&o.addEventListener("close",()=>i()),a&&o.addEventListener("versionchange",l=>a(l.oldVersion,l.newVersion,l))}).catch(()=>{}),c}function Pe(s,{blocked:e}={}){const t=indexedDB.deleteDatabase(s);return e&&t.addEventListener("blocked",n=>e(n.oldVersion,n)),f(t).then(()=>{})}const Ne=["get","getKey","getAll","getAllKeys","count"],ve=["put","add","delete","clear"],T=new Map;function O(s,e){if(!(s instanceof IDBDatabase&&!(e in s)&&typeof e=="string"))return;if(T.get(e))return T.get(e);const t=e.replace(/FromIndex$/,""),n=e!==t,a=ve.includes(t);if(!(t in(n?IDBIndex:IDBObjectStore).prototype)||!(a||Ne.includes(t)))return;const i=async function(r,...c){const o=this.transaction(r,a?"readwrite":"readonly");let l=o.store;return n&&(l=l.index(c.shift())),(await Promise.all([l[t](...c),a&&o.done]))[0]};return T.set(e,i),i}Ue(s=>({...s,get:(e,t,n)=>O(e,t)||s.get(e,t,n),has:(e,t)=>!!O(e,t)||s.has(e,t)}));try{self["workbox:expiration:7.3.0"]&&_()}catch{}const Me="workbox-expiration",w="cache-entries",S=s=>{const e=new URL(s,location.href);return e.hash="",e.href};class Ae{constructor(e){this._db=null,this._cacheName=e}_upgradeDb(e){const t=e.createObjectStore(w,{keyPath:"id"});t.createIndex("cacheName","cacheName",{unique:!1}),t.createIndex("timestamp","timestamp",{unique:!1})}_upgradeDbAndDeleteOldDbs(e){this._upgradeDb(e),this._cacheName&&Pe(this._cacheName)}async setTimestamp(e,t){e=S(e);const n={url:e,timestamp:t,cacheName:this._cacheName,id:this._getId(e)},i=(await this.getDb()).transaction(w,"readwrite",{durability:"relaxed"});await i.store.put(n),await i.done}async getTimestamp(e){const n=await(await this.getDb()).get(w,this._getId(e));return n==null?void 0:n.timestamp}async expireEntries(e,t){const n=await this.getDb();let a=await n.transaction(w).store.index("timestamp").openCursor(null,"prev");const i=[];let r=0;for(;a;){const o=a.value;o.cacheName===this._cacheName&&(e&&o.timestamp<e||t&&r>=t?i.push(a.value):r++),a=await a.continue()}const c=[];for(const o of i)await n.delete(w,o.id),c.push(o.url);return c}_getId(e){return this._cacheName+"|"+S(e)}async getDb(){return this._db||(this._db=await Ie(Me,1,{upgrade:this._upgradeDbAndDeleteOldDbs.bind(this)})),this._db}}class Ke{constructor(e,t={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=t.maxEntries,this._maxAgeSeconds=t.maxAgeSeconds,this._matchOptions=t.matchOptions,this._cacheName=e,this._timestampModel=new Ae(e)}async expireEntries(){if(this._isRunning){this._rerunRequested=!0;return}this._isRunning=!0;const e=this._maxAgeSeconds?Date.now()-this._maxAgeSeconds*1e3:0,t=await this._timestampModel.expireEntries(e,this._maxEntries),n=await self.caches.open(this._cacheName);for(const a of t)await n.delete(a,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,H(this.expireEntries()))}async updateTimestamp(e){await this._timestampModel.setTimestamp(e,Date.now())}async isURLExpired(e){if(this._maxAgeSeconds){const t=await this._timestampModel.getTimestamp(e),n=Date.now()-this._maxAgeSeconds*1e3;return t!==void 0?t<n:!0}else return!1}async delete(){this._rerunRequested=!1,await this._timestampModel.expireEntries(1/0)}}function Oe(s){B.add(s)}class Se{constructor(e={}){this.cachedResponseWillBeUsed=async({event:t,request:n,cacheName:a,cachedResponse:i})=>{if(!i)return null;const r=this._isResponseDateFresh(i),c=this._getCacheExpiration(a);H(c.expireEntries());const o=c.updateTimestamp(n.url);if(t)try{t.waitUntil(o)}catch{}return r?i:null},this.cacheDidUpdate=async({cacheName:t,request:n})=>{const a=this._getCacheExpiration(t);await a.updateTimestamp(n.url),await a.expireEntries()},this._config=e,this._maxAgeSeconds=e.maxAgeSeconds,this._cacheExpirations=new Map,e.purgeOnQuotaError&&Oe(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(e){if(e===b.getRuntimeName())throw new h("expire-custom-caches-only");let t=this._cacheExpirations.get(e);return t||(t=new Ke(e,this._config),this._cacheExpirations.set(e,t)),t}_isResponseDateFresh(e){if(!this._maxAgeSeconds)return!0;const t=this._getDateHeaderTimestamp(e);if(t===null)return!0;const n=Date.now();return t>=n-this._maxAgeSeconds*1e3}_getDateHeaderTimestamp(e){if(!e.headers.has("date"))return null;const t=e.headers.get("date"),a=new Date(t).getTime();return isNaN(a)?null:a}async deleteCacheAndMetadata(){for(const[e,t]of this._cacheExpirations)await self.caches.delete(e),await t.delete();this._cacheExpirations=new Map}}Re([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"0f93805414c783a30b72e0ce88f2c7c4","url":"icons/icon.svg"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":"0362e0eb00358646fd4c97674945adba","url":"icons/icon-180.png"},{"revision":null,"url":"assets/xychartDiagram-5P7HB3ND-Bdcd_98G.js"},{"revision":null,"url":"assets/wardleyDiagram-NUSXRM2D-4y-iyT2D.js"},{"revision":null,"url":"assets/wardley-RL74JXVD-DmgKZSUh.js"},{"revision":null,"url":"assets/vennDiagram-DHZGUBPP-KqcKNQ1-.js"},{"revision":null,"url":"assets/timeline-definition-GMOUNBTQ-Dcb9ue8q.js"},{"revision":null,"url":"assets/stateDiagram-v2-QKLJ7IA2-D1F0xws2.js"},{"revision":null,"url":"assets/stateDiagram-FHFEXIEX-WQkLynRi.js"},{"revision":null,"url":"assets/sequenceDiagram-FGHM5R23-CoFyaUFj.js"},{"revision":null,"url":"assets/sankeyDiagram-XADWPNL6-CP6XoGCk.js"},{"revision":null,"url":"assets/requirementDiagram-MS252O5E-CkL3sbnK.js"},{"revision":null,"url":"assets/quadrantDiagram-34T5L4WZ-pb0aN3QY.js"},{"revision":null,"url":"assets/pieDiagram-DEJITSTG-DQqclfI2.js"},{"revision":null,"url":"assets/ordinal-Cboi1Yqb.js"},{"revision":null,"url":"assets/mindmap-definition-QFDTVHPH-Bb4AuZN4.js"},{"revision":null,"url":"assets/linear-DCFOEcB6.js"},{"revision":null,"url":"assets/layout-ThSqQjtq.js"},{"revision":null,"url":"assets/katex-B1X10hvy.js"},{"revision":null,"url":"assets/kanban-definition-6JOO6SKY-BcvXQPfh.js"},{"revision":null,"url":"assets/journeyDiagram-VCZTEJTY-CJTv8kT4.js"},{"revision":null,"url":"assets/ishikawaDiagram-UXIWVN3A-6aQrUmM1.js"},{"revision":null,"url":"assets/init-Gi6I4Gst.js"},{"revision":null,"url":"assets/infoDiagram-42DDH7IO-CCYTG5TW.js"},{"revision":null,"url":"assets/index-KBnPi8DC.css"},{"revision":null,"url":"assets/index-Bp7KnjkK.js"},{"revision":null,"url":"assets/graph-DQMLsVKn.js"},{"revision":null,"url":"assets/gitGraphDiagram-UUTBAWPF-D0of7G0H.js"},{"revision":null,"url":"assets/ganttDiagram-T4ZO3ILL-BnT7GCzh.js"},{"revision":null,"url":"assets/flowDiagram-DWJPFMVM-CZa_uY2_.js"},{"revision":null,"url":"assets/erDiagram-SMLLAGMA-DLmNKAuD.js"},{"revision":null,"url":"assets/diagram-TYMM5635-Dl7dRWkC.js"},{"revision":null,"url":"assets/diagram-MMDJMWI5-C1yHkOFA.js"},{"revision":null,"url":"assets/diagram-G4DWMVQ6--1gv_wcM.js"},{"revision":null,"url":"assets/diagram-5BDNPKRD-DwScs67g.js"},{"revision":null,"url":"assets/defaultLocale-DX6XiGOO.js"},{"revision":null,"url":"assets/dagre-KV5264BT-BbosVmxG.js"},{"revision":null,"url":"assets/cytoscape.esm-BQaXIfA_.js"},{"revision":null,"url":"assets/cose-bilkent-S5V4N54A-B2XXKALr.js"},{"revision":null,"url":"assets/clone-DTHql6BK.js"},{"revision":null,"url":"assets/classDiagram-v2-HSJHXN6E-C0Xsg2c2.js"},{"revision":null,"url":"assets/classDiagram-6PBFFD2Q-C0Xsg2c2.js"},{"revision":null,"url":"assets/chunk-YZCP3GAM-B2BkSOHZ.js"},{"revision":null,"url":"assets/chunk-QZHKN3VN-JqEPJ-I8.js"},{"revision":null,"url":"assets/chunk-OYMX7WX6-Nt-YAKKo.js"},{"revision":null,"url":"assets/chunk-FMBD7UC4-CL6X-Bgf.js"},{"revision":null,"url":"assets/chunk-EDXVE4YY-CwJdMkPT.js"},{"revision":null,"url":"assets/chunk-55IACEB6-CCtV1y23.js"},{"revision":null,"url":"assets/chunk-4TB4RGXK-D1SjwnL0.js"},{"revision":null,"url":"assets/chunk-4BX2VUAB-CxYOWomN.js"},{"revision":null,"url":"assets/channel-Bz1ES3Md.js"},{"revision":null,"url":"assets/c4Diagram-AHTNJAMY-BwE7ZnCD.js"},{"revision":null,"url":"assets/blockDiagram-DXYQGD6D-BcStipzf.js"},{"revision":null,"url":"assets/architectureDiagram-Q4EWVU46-D_3Wy2pQ.js"},{"revision":null,"url":"assets/arc-DmuNthMW.js"},{"revision":null,"url":"assets/_baseUniq-DaY_Bc3O.js"},{"revision":null,"url":"assets/_basePickBy-BLefhu0l.js"},{"revision":"0362e0eb00358646fd4c97674945adba","url":"icons/icon-180.png"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"b0747e8d6cde0d45e05be8e5c731729e","url":"manifest.webmanifest"}]);we();q(({url:s})=>s.hostname==="cdn.jsdelivr.net"&&s.pathname.endsWith(".ttf"),new be({cacheName:"termbeam-fonts",plugins:[new Se({maxEntries:5,maxAgeSeconds:365*24*60*60})]}));self.addEventListener("message",s=>{var e;((e=s.data)==null?void 0:e.type)==="CLEAR_CACHES"&&caches.keys().then(t=>{for(const n of t)n!=="workbox-precache-v2"&&caches.delete(n)})});self.addEventListener("install",()=>{self.skipWaiting()});self.addEventListener("activate",s=>{s.waitUntil(caches.delete("termbeam-navigation").then(()=>self.clients.claim()))});self.addEventListener("push",s=>{let e={title:"Command finished",body:"TermBeam"};if(s.data)try{e=s.data.json()}catch{}s.waitUntil(self.clients.matchAll({type:"window",includeUncontrolled:!0}).then(async t=>{if(t.some(i=>i.url.includes(self.location.origin)&&i.focused))return;const a={body:e.body||"A command has completed",icon:"/icons/icon-192.png",badge:"/icons/icon-192.png",tag:e.tag||"termbeam-cmd",renotify:!0,data:{url:e.url||"/",type:e.type||"command-complete",sessionId:e.sessionId},vibrate:[200,100,200]};try{await self.navigator.setAppBadge(1)}catch{}return self.registration.showNotification(e.title||"Command finished",a)}))});self.addEventListener("notificationclick",s=>{s.notification.close();try{self.navigator.clearAppBadge()}catch{}const e=s.notification.data||{},t=e.url||"/",n=e.type||"";s.waitUntil(self.clients.matchAll({type:"window",includeUncontrolled:!0}).then(a=>{for(const i of a)if(i.url.includes(self.location.origin)&&"focus"in i)return n&&i.postMessage({type:"NOTIFICATION_CLICKED",notificationType:n,sessionId:e.sessionId}),i.focus();return self.clients.openWindow(t)}))});
2
+ This is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(c)}}}install(e){return v(e,async()=>{const t=new Y;this.strategy.plugins.push(t);for(const[i,r]of this._urlsToCacheKeys){const c=this._cacheKeysToIntegrities.get(r),o=this._urlsToCacheModes.get(i),l=new Request(i,{integrity:c,cache:o,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:r},request:l,event:e}))}const{updatedURLs:n,notUpdatedURLs:a}=t;return{updatedURLs:n,notUpdatedURLs:a}})}activate(e){return v(e,async()=>{const t=await self.caches.open(this.strategy.cacheName),n=await t.keys(),a=new Set(this._urlsToCacheKeys.values()),i=[];for(const r of n)a.has(r.url)||(await t.delete(r),i.push(r.url));return{deletedURLs:i}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){const t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){const t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){const t=this.getCacheKeyForURL(e);if(!t)throw new h("non-precached-url",{url:e});return n=>(n.request=new Request(e),n.params=Object.assign({cacheKey:t},n.params),this.strategy.handle(n))}}let D;const j=()=>(D||(D=new oe),D);try{self["workbox:routing:7.3.0"]&&_()}catch{}const F="GET",x=s=>s&&typeof s=="object"?s:{handle:s};class R{constructor(e,t,n=F){this.handler=x(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=x(e)}}class le extends R{constructor(e,t,n){const a=({url:i})=>{const r=e.exec(i.href);if(r&&!(i.origin!==location.origin&&r.index!==0))return r.slice(1)};super(a,t,n)}}class he{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",(e=>{const{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener("message",(e=>{if(e.data&&e.data.type==="CACHE_URLS"){const{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(a=>{typeof a=="string"&&(a=[a]);const i=new Request(...a);return this.handleRequest({request:i,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){const n=new URL(e.url,location.href);if(!n.protocol.startsWith("http"))return;const a=n.origin===location.origin,{params:i,route:r}=this.findMatchingRoute({event:t,request:e,sameOrigin:a,url:n});let c=r&&r.handler;const o=e.method;if(!c&&this._defaultHandlerMap.has(o)&&(c=this._defaultHandlerMap.get(o)),!c)return;let l;try{l=c.handle({url:n,request:e,event:t,params:i})}catch(u){l=Promise.reject(u)}const g=r&&r.catchHandler;return l instanceof Promise&&(this._catchHandler||g)&&(l=l.catch(async u=>{if(g)try{return await g.handle({url:n,request:e,event:t,params:i})}catch(N){N instanceof Error&&(u=N)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw u})),l}findMatchingRoute({url:e,sameOrigin:t,request:n,event:a}){const i=this._routes.get(n.method)||[];for(const r of i){let c;const o=r.match({url:e,sameOrigin:t,request:n,event:a});if(o)return c=o,(Array.isArray(c)&&c.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o=="boolean")&&(c=void 0),{route:r,params:c}}return{}}setDefaultHandler(e,t=F){this._defaultHandlerMap.set(t,x(e))}setCatchHandler(e){this._catchHandler=x(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new h("unregister-route-but-not-found-with-method",{method:e.method});const t=this._routes.get(e.method).indexOf(e);if(t>-1)this._routes.get(e.method).splice(t,1);else throw new h("unregister-route-route-not-registered")}}let y;const ue=()=>(y||(y=new he,y.addFetchListener(),y.addCacheListener()),y);function q(s,e,t){let n;if(typeof s=="string"){const i=new URL(s,location.href),r=({url:c})=>c.href===i.href;n=new R(r,e,t)}else if(s instanceof RegExp)n=new le(s,e,t);else if(typeof s=="function")n=new R(s,e,t);else if(s instanceof R)n=s;else throw new h("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});return ue().registerRoute(n),n}function de(s,e=[]){for(const t of[...s.searchParams.keys()])e.some(n=>n.test(t))&&s.searchParams.delete(t);return s}function*fe(s,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:t="index.html",cleanURLs:n=!0,urlManipulation:a}={}){const i=new URL(s,location.href);i.hash="",yield i.href;const r=de(i,e);if(yield r.href,t&&r.pathname.endsWith("/")){const c=new URL(r.href);c.pathname+=t,yield c.href}if(n){const c=new URL(r.href);c.pathname+=".html",yield c.href}if(a){const c=a({url:i});for(const o of c)yield o.href}}class pe extends R{constructor(e,t){const n=({request:a})=>{const i=e.getURLsToCacheKeys();for(const r of fe(a.url,t)){const c=i.get(r);if(c){const o=e.getIntegrityForCacheKey(c);return{cacheKey:c,integrity:o}}}};super(n,e.strategy)}}function ge(s){const e=j(),t=new pe(e,s);q(t)}const me="-precache-",ye=async(s,e=me)=>{const n=(await self.caches.keys()).filter(a=>a.includes(e)&&a.includes(self.registration.scope)&&a!==s);return await Promise.all(n.map(a=>self.caches.delete(a))),n};function we(){self.addEventListener("activate",(s=>{const e=b.getPrecacheName();s.waitUntil(ye(e).then(t=>{}))}))}function _e(s){j().precache(s)}function Re(s,e){_e(s),ge(e)}class be extends W{async _handle(e,t){let n=await t.cacheMatch(e),a;if(!n)try{n=await t.fetchAndCachePut(e)}catch(i){i instanceof Error&&(a=i)}if(!n)throw new h("no-response",{url:e.url,error:a});return n}}function H(s){s.then(()=>{})}const Ce=(s,e)=>e.some(t=>s instanceof t);let A,K;function xe(){return A||(A=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function Ee(){return K||(K=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const V=new WeakMap,k=new WeakMap,$=new WeakMap,L=new WeakMap,P=new WeakMap;function De(s){const e=new Promise((t,n)=>{const a=()=>{s.removeEventListener("success",i),s.removeEventListener("error",r)},i=()=>{t(f(s.result)),a()},r=()=>{n(s.error),a()};s.addEventListener("success",i),s.addEventListener("error",r)});return e.then(t=>{t instanceof IDBCursor&&V.set(t,s)}).catch(()=>{}),P.set(e,s),e}function Le(s){if(k.has(s))return;const e=new Promise((t,n)=>{const a=()=>{s.removeEventListener("complete",i),s.removeEventListener("error",r),s.removeEventListener("abort",r)},i=()=>{t(),a()},r=()=>{n(s.error||new DOMException("AbortError","AbortError")),a()};s.addEventListener("complete",i),s.addEventListener("error",r),s.addEventListener("abort",r)});k.set(s,e)}let I={get(s,e,t){if(s instanceof IDBTransaction){if(e==="done")return k.get(s);if(e==="objectStoreNames")return s.objectStoreNames||$.get(s);if(e==="store")return t.objectStoreNames[1]?void 0:t.objectStore(t.objectStoreNames[0])}return f(s[e])},set(s,e,t){return s[e]=t,!0},has(s,e){return s instanceof IDBTransaction&&(e==="done"||e==="store")?!0:e in s}};function Ue(s){I=s(I)}function Te(s){return s===IDBDatabase.prototype.transaction&&!("objectStoreNames"in IDBTransaction.prototype)?function(e,...t){const n=s.call(U(this),e,...t);return $.set(n,e.sort?e.sort():[e]),f(n)}:Ee().includes(s)?function(...e){return s.apply(U(this),e),f(V.get(this))}:function(...e){return f(s.apply(U(this),e))}}function ke(s){return typeof s=="function"?Te(s):(s instanceof IDBTransaction&&Le(s),Ce(s,xe())?new Proxy(s,I):s)}function f(s){if(s instanceof IDBRequest)return De(s);if(L.has(s))return L.get(s);const e=ke(s);return e!==s&&(L.set(s,e),P.set(e,s)),e}const U=s=>P.get(s);function Ie(s,e,{blocked:t,upgrade:n,blocking:a,terminated:i}={}){const r=indexedDB.open(s,e),c=f(r);return n&&r.addEventListener("upgradeneeded",o=>{n(f(r.result),o.oldVersion,o.newVersion,f(r.transaction),o)}),t&&r.addEventListener("blocked",o=>t(o.oldVersion,o.newVersion,o)),c.then(o=>{i&&o.addEventListener("close",()=>i()),a&&o.addEventListener("versionchange",l=>a(l.oldVersion,l.newVersion,l))}).catch(()=>{}),c}function Pe(s,{blocked:e}={}){const t=indexedDB.deleteDatabase(s);return e&&t.addEventListener("blocked",n=>e(n.oldVersion,n)),f(t).then(()=>{})}const Ne=["get","getKey","getAll","getAllKeys","count"],ve=["put","add","delete","clear"],T=new Map;function O(s,e){if(!(s instanceof IDBDatabase&&!(e in s)&&typeof e=="string"))return;if(T.get(e))return T.get(e);const t=e.replace(/FromIndex$/,""),n=e!==t,a=ve.includes(t);if(!(t in(n?IDBIndex:IDBObjectStore).prototype)||!(a||Ne.includes(t)))return;const i=async function(r,...c){const o=this.transaction(r,a?"readwrite":"readonly");let l=o.store;return n&&(l=l.index(c.shift())),(await Promise.all([l[t](...c),a&&o.done]))[0]};return T.set(e,i),i}Ue(s=>({...s,get:(e,t,n)=>O(e,t)||s.get(e,t,n),has:(e,t)=>!!O(e,t)||s.has(e,t)}));try{self["workbox:expiration:7.3.0"]&&_()}catch{}const Me="workbox-expiration",w="cache-entries",S=s=>{const e=new URL(s,location.href);return e.hash="",e.href};class Ae{constructor(e){this._db=null,this._cacheName=e}_upgradeDb(e){const t=e.createObjectStore(w,{keyPath:"id"});t.createIndex("cacheName","cacheName",{unique:!1}),t.createIndex("timestamp","timestamp",{unique:!1})}_upgradeDbAndDeleteOldDbs(e){this._upgradeDb(e),this._cacheName&&Pe(this._cacheName)}async setTimestamp(e,t){e=S(e);const n={url:e,timestamp:t,cacheName:this._cacheName,id:this._getId(e)},i=(await this.getDb()).transaction(w,"readwrite",{durability:"relaxed"});await i.store.put(n),await i.done}async getTimestamp(e){const n=await(await this.getDb()).get(w,this._getId(e));return n==null?void 0:n.timestamp}async expireEntries(e,t){const n=await this.getDb();let a=await n.transaction(w).store.index("timestamp").openCursor(null,"prev");const i=[];let r=0;for(;a;){const o=a.value;o.cacheName===this._cacheName&&(e&&o.timestamp<e||t&&r>=t?i.push(a.value):r++),a=await a.continue()}const c=[];for(const o of i)await n.delete(w,o.id),c.push(o.url);return c}_getId(e){return this._cacheName+"|"+S(e)}async getDb(){return this._db||(this._db=await Ie(Me,1,{upgrade:this._upgradeDbAndDeleteOldDbs.bind(this)})),this._db}}class Ke{constructor(e,t={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=t.maxEntries,this._maxAgeSeconds=t.maxAgeSeconds,this._matchOptions=t.matchOptions,this._cacheName=e,this._timestampModel=new Ae(e)}async expireEntries(){if(this._isRunning){this._rerunRequested=!0;return}this._isRunning=!0;const e=this._maxAgeSeconds?Date.now()-this._maxAgeSeconds*1e3:0,t=await this._timestampModel.expireEntries(e,this._maxEntries),n=await self.caches.open(this._cacheName);for(const a of t)await n.delete(a,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,H(this.expireEntries()))}async updateTimestamp(e){await this._timestampModel.setTimestamp(e,Date.now())}async isURLExpired(e){if(this._maxAgeSeconds){const t=await this._timestampModel.getTimestamp(e),n=Date.now()-this._maxAgeSeconds*1e3;return t!==void 0?t<n:!0}else return!1}async delete(){this._rerunRequested=!1,await this._timestampModel.expireEntries(1/0)}}function Oe(s){B.add(s)}class Se{constructor(e={}){this.cachedResponseWillBeUsed=async({event:t,request:n,cacheName:a,cachedResponse:i})=>{if(!i)return null;const r=this._isResponseDateFresh(i),c=this._getCacheExpiration(a);H(c.expireEntries());const o=c.updateTimestamp(n.url);if(t)try{t.waitUntil(o)}catch{}return r?i:null},this.cacheDidUpdate=async({cacheName:t,request:n})=>{const a=this._getCacheExpiration(t);await a.updateTimestamp(n.url),await a.expireEntries()},this._config=e,this._maxAgeSeconds=e.maxAgeSeconds,this._cacheExpirations=new Map,e.purgeOnQuotaError&&Oe(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(e){if(e===b.getRuntimeName())throw new h("expire-custom-caches-only");let t=this._cacheExpirations.get(e);return t||(t=new Ke(e,this._config),this._cacheExpirations.set(e,t)),t}_isResponseDateFresh(e){if(!this._maxAgeSeconds)return!0;const t=this._getDateHeaderTimestamp(e);if(t===null)return!0;const n=Date.now();return t>=n-this._maxAgeSeconds*1e3}_getDateHeaderTimestamp(e){if(!e.headers.has("date"))return null;const t=e.headers.get("date"),a=new Date(t).getTime();return isNaN(a)?null:a}async deleteCacheAndMetadata(){for(const[e,t]of this._cacheExpirations)await self.caches.delete(e),await t.delete();this._cacheExpirations=new Map}}Re([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"0f93805414c783a30b72e0ce88f2c7c4","url":"icons/icon.svg"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":"0362e0eb00358646fd4c97674945adba","url":"icons/icon-180.png"},{"revision":null,"url":"assets/xychartDiagram-5P7HB3ND-cd-6HXrN.js"},{"revision":null,"url":"assets/wardleyDiagram-NUSXRM2D-Dsy9JWUf.js"},{"revision":null,"url":"assets/wardley-RL74JXVD-BEjx3hAD.js"},{"revision":null,"url":"assets/vennDiagram-DHZGUBPP-DoHPigKa.js"},{"revision":null,"url":"assets/timeline-definition-GMOUNBTQ-C3o7gZFF.js"},{"revision":null,"url":"assets/stateDiagram-v2-QKLJ7IA2-C7M79J7F.js"},{"revision":null,"url":"assets/stateDiagram-FHFEXIEX-X9kal6wR.js"},{"revision":null,"url":"assets/sequenceDiagram-FGHM5R23-Dnl-W6jS.js"},{"revision":null,"url":"assets/sankeyDiagram-XADWPNL6-BHPnOiHK.js"},{"revision":null,"url":"assets/requirementDiagram-MS252O5E-fSM1Pi3V.js"},{"revision":null,"url":"assets/quadrantDiagram-34T5L4WZ-DloaxY2h.js"},{"revision":null,"url":"assets/pieDiagram-DEJITSTG-DlYgVpVr.js"},{"revision":null,"url":"assets/ordinal-Cboi1Yqb.js"},{"revision":null,"url":"assets/mindmap-definition-QFDTVHPH-DQUtHqQ6.js"},{"revision":null,"url":"assets/linear-s0Mg7155.js"},{"revision":null,"url":"assets/layout-Bcu4s7Ho.js"},{"revision":null,"url":"assets/katex-B1X10hvy.js"},{"revision":null,"url":"assets/kanban-definition-6JOO6SKY-NjVvkzyg.js"},{"revision":null,"url":"assets/journeyDiagram-VCZTEJTY-Cx-gOesl.js"},{"revision":null,"url":"assets/ishikawaDiagram-UXIWVN3A-DZdSiihk.js"},{"revision":null,"url":"assets/init-Gi6I4Gst.js"},{"revision":null,"url":"assets/infoDiagram-42DDH7IO-CTZf-XaE.js"},{"revision":null,"url":"assets/index-DWaSRzf6.css"},{"revision":null,"url":"assets/index-CwjgIG7M.js"},{"revision":null,"url":"assets/graph-DY36UTy7.js"},{"revision":null,"url":"assets/gitGraphDiagram-UUTBAWPF-CouNbB0H.js"},{"revision":null,"url":"assets/ganttDiagram-T4ZO3ILL-D5Ik9clK.js"},{"revision":null,"url":"assets/flowDiagram-DWJPFMVM-DUlTxDrh.js"},{"revision":null,"url":"assets/erDiagram-SMLLAGMA-DgukEqTQ.js"},{"revision":null,"url":"assets/diagram-TYMM5635-CLYhOm9a.js"},{"revision":null,"url":"assets/diagram-MMDJMWI5-B6-WK_TJ.js"},{"revision":null,"url":"assets/diagram-G4DWMVQ6-DD5Ucpcn.js"},{"revision":null,"url":"assets/diagram-5BDNPKRD-4Km3IxIT.js"},{"revision":null,"url":"assets/defaultLocale-DX6XiGOO.js"},{"revision":null,"url":"assets/dagre-KV5264BT-CiBddJE9.js"},{"revision":null,"url":"assets/cytoscape.esm-BQaXIfA_.js"},{"revision":null,"url":"assets/cose-bilkent-S5V4N54A-CsbF4Rbc.js"},{"revision":null,"url":"assets/clone-iFtwY3RV.js"},{"revision":null,"url":"assets/classDiagram-v2-HSJHXN6E-DRtX5Ta8.js"},{"revision":null,"url":"assets/classDiagram-6PBFFD2Q-DRtX5Ta8.js"},{"revision":null,"url":"assets/chunk-YZCP3GAM-qiJvjghT.js"},{"revision":null,"url":"assets/chunk-QZHKN3VN-CyNtEZcY.js"},{"revision":null,"url":"assets/chunk-OYMX7WX6-v5mXWXoC.js"},{"revision":null,"url":"assets/chunk-FMBD7UC4-CxmTHyai.js"},{"revision":null,"url":"assets/chunk-EDXVE4YY-BgWTXLsq.js"},{"revision":null,"url":"assets/chunk-55IACEB6-BTW1fQoW.js"},{"revision":null,"url":"assets/chunk-4TB4RGXK-DDonZyK6.js"},{"revision":null,"url":"assets/chunk-4BX2VUAB-Cob7CgE_.js"},{"revision":null,"url":"assets/channel-DSjdyO61.js"},{"revision":null,"url":"assets/c4Diagram-AHTNJAMY-BYDCN8H0.js"},{"revision":null,"url":"assets/blockDiagram-DXYQGD6D-wN2o-9_g.js"},{"revision":null,"url":"assets/architectureDiagram-Q4EWVU46-BmFTw0nZ.js"},{"revision":null,"url":"assets/arc-BNbndmGK.js"},{"revision":null,"url":"assets/_baseUniq-DnMFuvsx.js"},{"revision":null,"url":"assets/_basePickBy-BIHCnP-C.js"},{"revision":"0362e0eb00358646fd4c97674945adba","url":"icons/icon-180.png"},{"revision":"75734e6b38a556148f51b9e10eeb01c8","url":"icons/icon-192.png"},{"revision":"5dee5ddcd8e8533edb348118334d9756","url":"icons/icon-512.png"},{"revision":"b0747e8d6cde0d45e05be8e5c731729e","url":"manifest.webmanifest"}]);we();q(({url:s})=>s.hostname==="cdn.jsdelivr.net"&&s.pathname.endsWith(".ttf"),new be({cacheName:"termbeam-fonts",plugins:[new Se({maxEntries:5,maxAgeSeconds:365*24*60*60})]}));self.addEventListener("message",s=>{var e;((e=s.data)==null?void 0:e.type)==="CLEAR_CACHES"&&caches.keys().then(t=>{for(const n of t)n!=="workbox-precache-v2"&&caches.delete(n)})});self.addEventListener("install",()=>{self.skipWaiting()});self.addEventListener("activate",s=>{s.waitUntil(caches.delete("termbeam-navigation").then(()=>self.clients.claim()))});self.addEventListener("push",s=>{let e={title:"Command finished",body:"TermBeam"};if(s.data)try{e=s.data.json()}catch{}s.waitUntil(self.clients.matchAll({type:"window",includeUncontrolled:!0}).then(async t=>{if(t.some(i=>i.url.includes(self.location.origin)&&i.focused))return;const a={body:e.body||"A command has completed",icon:"/icons/icon-192.png",badge:"/icons/icon-192.png",tag:e.tag||"termbeam-cmd",renotify:!0,data:{url:e.url||"/",type:e.type||"command-complete",sessionId:e.sessionId},vibrate:[200,100,200]};try{await self.navigator.setAppBadge(1)}catch{}return self.registration.showNotification(e.title||"Command finished",a)}))});self.addEventListener("notificationclick",s=>{s.notification.close();try{self.navigator.clearAppBadge()}catch{}const e=s.notification.data||{},t=e.url||"/",n=e.type||"";s.waitUntil(self.clients.matchAll({type:"window",includeUncontrolled:!0}).then(a=>{for(const i of a)if(i.url.includes(self.location.origin)&&"focus"in i)return n&&i.postMessage({type:"NOTIFICATION_CLICKED",notificationType:n,sessionId:e.sessionId}),i.focus();return self.clients.openWindow(t)}))});
@@ -156,6 +156,37 @@ function setupRoutes(app, { auth, sessions, config, state, pushManager, copilotS
156
156
  res.json({ version: getVersion() });
157
157
  });
158
158
 
159
+ // Changelog — served from repo CHANGELOG.md (bundled with the npm package).
160
+ // Falls back to GitHub raw if the file isn't present locally.
161
+ // Cached for 1 hour since it only changes on release.
162
+ app.get('/api/changelog', apiRateLimit, auth.middleware, async (_req, res) => {
163
+ const changelogPath = path.join(__dirname, '..', '..', 'CHANGELOG.md');
164
+ fs.readFile(changelogPath, 'utf8', async (err, data) => {
165
+ if (!err) {
166
+ res.set('Cache-Control', 'private, max-age=3600');
167
+ return res.type('text/markdown').send(data);
168
+ }
169
+ if (err.code !== 'ENOENT') {
170
+ log.warn('Failed to read local CHANGELOG.md', { code: err.code });
171
+ return res.status(500).json({ error: 'Failed to read changelog' });
172
+ }
173
+ try {
174
+ const response = await fetch(
175
+ 'https://raw.githubusercontent.com/dorlugasigal/TermBeam/main/CHANGELOG.md',
176
+ { signal: AbortSignal.timeout(5000) },
177
+ );
178
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
179
+ const text = await response.text();
180
+ res.set('Cache-Control', 'private, max-age=3600');
181
+ res.type('text/markdown').send(text);
182
+ } catch (fetchErr) {
183
+ const msg = fetchErr instanceof Error ? fetchErr.message : String(fetchErr);
184
+ log.debug('Changelog not available', { err: msg });
185
+ res.status(404).json({ error: 'Changelog not available' });
186
+ }
187
+ });
188
+ });
189
+
159
190
  // Public config — no auth required
160
191
  app.get('/api/config', (_req, res) => {
161
192
  res.json({ passwordRequired: !!auth.password });
@@ -2,6 +2,7 @@ const { execSync, execFileSync, execFile, spawn } = require('child_process');
2
2
  const path = require('path');
3
3
  const fs = require('fs');
4
4
  const os = require('os');
5
+ const dns = require('dns');
5
6
  const EventEmitter = require('events');
6
7
  const log = require('../utils/logger');
7
8
  const { promptInstall } = require('./install');
@@ -26,15 +27,38 @@ let waitingForAuth = false;
26
27
  let authCheckInterval = null;
27
28
  let expiryWarned = false;
28
29
 
30
+ // --- Network-wait state ---
31
+ let waitingForNetwork = false;
32
+ let networkWaitInterval = null;
33
+
29
34
  const HEALTH_CHECK_INTERVAL = 30_000; // 30s between checks
30
35
  const HEALTH_CHECK_GRACE = 2; // 2 consecutive failures before restart
31
36
  const MAX_RESTART_ATTEMPTS = 10;
32
37
  const BACKOFF_DELAYS = [1000, 2000, 5000, 10_000, 15_000, 30_000]; // then stays at 30s
33
38
  const AUTH_CHECK_INTERVAL = 30_000; // 30s between auth re-checks
39
+ const NETWORK_CHECK_INTERVAL = 60_000; // 60s between network reachability probes
40
+ const NETWORK_PROBE_HOST = 'global.rel.tunnels.api.visualstudio.com';
41
+ const NETWORK_PROBE_TIMEOUT = 5_000;
34
42
  const TOKEN_EXPIRY_WARN_SECONDS = 3600; // warn at 1 hour remaining
35
43
 
36
44
  const AUTH_ERROR_PATTERNS = ['login required', 'not logged in', 'sign in required'];
37
45
 
46
+ // DNS / transient network failures that should NOT burn restart attempts.
47
+ // These typically resolve on their own once the host regains connectivity
48
+ // (e.g. Wi-Fi sleep/wake, router reboot, upstream DNS hiccup).
49
+ const NETWORK_ERROR_PATTERNS = [
50
+ 'nodename nor servname',
51
+ 'getaddrinfo',
52
+ 'enotfound',
53
+ 'eai_again',
54
+ 'econnrefused',
55
+ 'econnreset',
56
+ 'etimedout',
57
+ 'network is unreachable',
58
+ 'no such host',
59
+ 'temporary failure in name resolution',
60
+ ];
61
+
38
62
  const SAFE_ID_RE = /^[a-zA-Z0-9._-]+$/;
39
63
 
40
64
  const DEVICE_CODE_INITIAL_TIMEOUT = 15000;
@@ -45,6 +69,37 @@ function isAuthError(message) {
45
69
  return AUTH_ERROR_PATTERNS.some((p) => lower.includes(p));
46
70
  }
47
71
 
72
+ function isNetworkError(message) {
73
+ const lower = (message || '').toLowerCase();
74
+ return NETWORK_ERROR_PATTERNS.some((p) => lower.includes(p));
75
+ }
76
+
77
+ function isNetworkReachable() {
78
+ return new Promise((resolve) => {
79
+ let settled = false;
80
+ const timer = setTimeout(() => {
81
+ if (!settled) {
82
+ settled = true;
83
+ resolve(false);
84
+ }
85
+ }, NETWORK_PROBE_TIMEOUT);
86
+ try {
87
+ dns.lookup(NETWORK_PROBE_HOST, (err) => {
88
+ if (settled) return;
89
+ settled = true;
90
+ clearTimeout(timer);
91
+ resolve(!err);
92
+ });
93
+ } catch {
94
+ if (!settled) {
95
+ settled = true;
96
+ clearTimeout(timer);
97
+ resolve(false);
98
+ }
99
+ }
100
+ });
101
+ }
102
+
48
103
  function isLoggedIn() {
49
104
  try {
50
105
  const out = execFileSync(devtunnelCmd, ['user', 'show'], {
@@ -210,7 +265,7 @@ let isPersisted = false;
210
265
  // --- Watchdog: health check & auto-restart ---
211
266
 
212
267
  function checkTunnelHealth() {
213
- if (!tunnelId || !tunnelProc || isRestarting || waitingForAuth) return;
268
+ if (!tunnelId || !tunnelProc || isRestarting || waitingForAuth || waitingForNetwork) return;
214
269
 
215
270
  const abortCtrl = new AbortController();
216
271
  const timer = setTimeout(() => abortCtrl.abort(), 10_000);
@@ -229,6 +284,17 @@ function checkTunnelHealth() {
229
284
  return;
230
285
  }
231
286
 
287
+ // Transient network errors (DNS, connection refused): the host has
288
+ // lost connectivity. Don't burn restart attempts — wait for network.
289
+ if (isNetworkError(err.message) || isNetworkError(err.stderr)) {
290
+ log.warn(`Tunnel health check: network unreachable — pausing until connectivity returns`);
291
+ stopHealthCheck();
292
+ killTunnelProc();
293
+ tunnelEvents.emit('disconnected');
294
+ startNetworkWait();
295
+ return;
296
+ }
297
+
232
298
  // "Tunnel not found" can mean the user's auth expired (CLI can't
233
299
  // query the tunnel without valid credentials). Check login status
234
300
  // to distinguish from a genuinely deleted tunnel.
@@ -389,13 +455,58 @@ function stopAuthWait() {
389
455
  }
390
456
  }
391
457
 
458
+ function startNetworkWait() {
459
+ if (waitingForNetwork) return;
460
+ waitingForNetwork = true;
461
+ isRestarting = false;
462
+ restartAttempts = 0;
463
+ consecutiveFailures = 0;
464
+
465
+ log.warn('Tunnel paused — waiting for network connectivity.');
466
+ log.warn('Will auto-resume when the tunnel service is reachable.');
467
+ tunnelEvents.emit('network-lost');
468
+
469
+ const probe = async () => {
470
+ if (!waitingForNetwork) return;
471
+ // If auth expired while we were offline, switch to auth-wait instead.
472
+ if (!isLoggedIn()) {
473
+ log.warn('DevTunnel auth expired during network outage — waiting for re-authentication');
474
+ stopNetworkWait();
475
+ handleAuthExpiration();
476
+ return;
477
+ }
478
+ if (await isNetworkReachable()) {
479
+ log.info('Network connectivity restored — resuming tunnel');
480
+ stopNetworkWait();
481
+ tunnelEvents.emit('network-restored');
482
+ scheduleRestart();
483
+ }
484
+ };
485
+
486
+ networkWaitInterval = setInterval(probe, NETWORK_CHECK_INTERVAL);
487
+ networkWaitInterval.unref();
488
+ // Also probe once immediately in case the outage already cleared.
489
+ probe();
490
+ }
491
+
492
+ function stopNetworkWait() {
493
+ waitingForNetwork = false;
494
+ if (networkWaitInterval) {
495
+ clearInterval(networkWaitInterval);
496
+ networkWaitInterval = null;
497
+ }
498
+ }
499
+
392
500
  function scheduleRestart() {
501
+ if (waitingForNetwork || waitingForAuth) return;
502
+
393
503
  if (restartAttempts >= MAX_RESTART_ATTEMPTS) {
394
- log.error(
395
- `Tunnel restart failed after ${MAX_RESTART_ATTEMPTS} attempts — giving up. Tunnel URL is unreachable.`,
504
+ log.warn(
505
+ `Tunnel restart failed after ${MAX_RESTART_ATTEMPTS} attempts — entering network-wait mode.`,
396
506
  );
397
507
  tunnelEvents.emit('failed', { attempts: restartAttempts });
398
508
  isRestarting = false;
509
+ startNetworkWait();
399
510
  return;
400
511
  }
401
512
 
@@ -428,11 +539,20 @@ function scheduleRestart() {
428
539
  } else {
429
540
  log.warn('Tunnel restart returned no URL');
430
541
  isRestarting = false;
542
+ // If the host appears to be offline, stop burning attempts.
543
+ if (!(await isNetworkReachable())) {
544
+ startNetworkWait();
545
+ return;
546
+ }
431
547
  scheduleRestart();
432
548
  }
433
549
  } catch (err) {
434
550
  log.error(`Tunnel restart error: ${err.message}`);
435
551
  isRestarting = false;
552
+ if (isNetworkError(err.message) || !(await isNetworkReachable())) {
553
+ startNetworkWait();
554
+ return;
555
+ }
436
556
  scheduleRestart();
437
557
  }
438
558
  }, delay);
@@ -635,9 +755,10 @@ async function startTunnel(port, options = {}) {
635
755
  }
636
756
 
637
757
  function cleanupTunnel() {
638
- // Stop watchdog and auth-wait to prevent restart during cleanup
758
+ // Stop watchdog, auth-wait, and network-wait to prevent restart during cleanup
639
759
  stopHealthCheck();
640
760
  stopAuthWait();
761
+ stopNetworkWait();
641
762
  isRestarting = true; // prevent exit handler from restarting
642
763
  if (restartTimer) {
643
764
  clearTimeout(restartTimer);
@@ -674,4 +795,9 @@ module.exports = {
674
795
  tunnelEvents,
675
796
  getLoginInfo,
676
797
  parseLoginInfo,
798
+ // Exported for tests
799
+ _internal: {
800
+ isNetworkError,
801
+ isAuthError,
802
+ },
677
803
  };
@@ -1 +0,0 @@
1
- import{aq as o,ar as n}from"./index-Bp7KnjkK.js";const t=(r,a)=>o.lang.round(n.parse(r)[a]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-D1SjwnL0.js";import{_ as i}from"./index-Bp7KnjkK.js";import"./chunk-FMBD7UC4-CL6X-Bgf.js";import"./chunk-YZCP3GAM-B2BkSOHZ.js";import"./chunk-55IACEB6-CCtV1y23.js";import"./chunk-EDXVE4YY-CwJdMkPT.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-D1SjwnL0.js";import{_ as i}from"./index-Bp7KnjkK.js";import"./chunk-FMBD7UC4-CL6X-Bgf.js";import"./chunk-YZCP3GAM-B2BkSOHZ.js";import"./chunk-55IACEB6-CCtV1y23.js";import"./chunk-EDXVE4YY-CwJdMkPT.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{b as r}from"./_baseUniq-DaY_Bc3O.js";var e=4;function a(o){return r(o,e)}export{a as c};