@rsc-kit/core 0.30.21 → 0.30.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"segmentStore.js","sourceRoot":"","sources":["../../src/js/segmentStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAuDH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAE3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;AAC7C,2DAA2D;AAC3D,IAAI,IAAI,GAAG,CAAC,CAAC;AACb,6EAA6E;AAC7E,IAAI,aAAa,GAAG,CAAC,CAAC;AACtB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEnD,SAAS,MAAM,CAAC,KAAa;IAC3B,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,QAAkB;IAElB,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAE/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;QAChB,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAElB,OAAO,GAAG,EAAE;QACV,GAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtB,IAAI,GAAI,CAAC,IAAI,KAAK,CAAC;YAAE,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACnC,CAAC;AAED,uDAAuD;AACvD,SAAS,MAAM,CACb,OAAyB,EACzB,KAAwB,EACxB,SAAiB;IAEjB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC;IAErC,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC;QACjF,KAAK,EAAE,IAAI;QACX,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,GAAG,CAAC,KAAa,EAAE,GAAW,EAAE,IAAU,EAAE,QAAiB;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,8DAA8D;IAC9D,MAAM,IAAI,GAAG,QAAQ,IAAI,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,QAAQ,CAAC;IACrF,MAAM,OAAO,GAAG;QACd,GAAG,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAC9D,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;KAC9G,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAEtE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,GAAW,EAAE,IAAU,EAAE,SAAyB;IAC1F,0EAA0E;IAC1E,qEAAqE;IACrE,uEAAuE;IACvE,uDAAuD;IACvD,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE5B,4EAA4E;IAC5E,4EAA4E;IAC5E,iEAAiE;IACjE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,QAAQ,GACZ,SAAS,IAAI,SAAS,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAClF,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC;QACzD,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;YAChB,GAAG,KAAK;YACR,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC;YAC5D,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,GAAG,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAElF,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;IAC1D,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAExC,MAAM,CAAC,KAAK,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,eAAe,CAAC,KAAa,EAAE,MAAe;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC;QAAE,OAAO;IAEvF,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;QAChB,GAAG,KAAK;QACR,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC;KACrF,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,GAAW,EAAE,IAAU;IACrE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,wEAAwE;IACxE,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,UAAU;IACV,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAAE,OAAO;IAE7D,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;QAChB,GAAG,KAAK;QACR,OAAO,EAAE;YACP,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;YACtD,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;SAC9D;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CAAC,CAAC;AAChB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,GAAW;IACtD,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC;AACrG,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,IAAU;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAE5E,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO;IAE5C,yEAAyE;IACzE,sEAAsE;IACtE,qEAAqE;IACrE,sEAAsE;IACtE,sEAAsE;IACtE,qEAAqE;IACrE,yDAAyD;IACzD,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;QAChB,GAAG,KAAK;QACR,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;KACvF,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,CAAC,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,GAAW,EAAE,IAAU,EAAE,QAAiB;IACnF,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAAE,OAAO;IAE9D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEd,OAAO;IACT,CAAC;IAED,0EAA0E;IAC1E,yDAAyD;IACzD,MAAM,CAAC,GAAG,CACR,KAAK,EACL,MAAM,CACJ,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACnI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,EAC9C,KAAK,CAAC,SAAS,CAChB,CACF,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,GAAW,EAAE,MAAe;IACjD,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAClD,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAC/H,CAAC;IAEF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAEtC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU;IACxB,qEAAqE;IACrE,qEAAqE;IACrE,wEAAwE;IACxE,6DAA6D;IAC7D,aAAa,GAAG,EAAE,IAAI,CAAC;IAEvB,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC;YAAE,SAAS;QAE7F,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;YACvE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;YAC3D,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,MAAe;IAC1D,uEAAuE;IACvE,gEAAgE;IAChE,yEAAyE;IACzE,yDAAyD;IACzD,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,GAAG,aAAa,CAAC,CAC7G,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACjC,MAAM;aACH,GAAG,CAAC,CAAC,CAAE;aACP,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;aAC5C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAC5B,CAAC;QAEF,wEAAwE;QACxE,6CAA6C;QAC7C,0EAA0E;QAC1E,yBAAyB;QACzB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,MAAM;YAAE,OAAO,KAAK,CAAC;IAC7D,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAEpC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;QAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjB,MAAM,CAAC,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,eAAe,CAAC,CAAC,CAAC,CAAC;QAEnB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;QAE7B,MAAM,CAAC,GAAG,CACR,CAAC,EACD,MAAM,CACJ,KAAK,CAAC,OAAO,EACb,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,EAC9C,GAAG,CACJ,CACF,CAAC;QACF,MAAM,CAAC,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,GAAG;QAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;GASG;AACH,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,MAAM,UAAU,cAAc;IAC5B,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["/**\n * What each segment boundary is showing, and what it is keeping alive behind it.\n *\n * A navigation replaces one segment. Keeping the previous one mounted — hidden,\n * not unmounted — is what lets going back restore it with its client state:\n * the half-typed form, the open disclosure, the scrolled list. Unmounting\n * throws all of that away, which is what replacing the root used to do.\n *\n * Entries are keyed by page (the URL, or its intercept variant), so a boundary\n * can hold several and reveal one. Empty is meaningful: a boundary with nothing\n * stored renders the children the server gave it.\n *\n * A store rather than state, and not a preference — three things rule state out.\n * A boundary is inserted between every layout level, so there are several and a\n * navigation targets one by depth; they are separated by server components, so\n * no setter can be threaded down to them, because a function does not cross\n * that boundary; and navigate.ts is a plain module with no component instance\n * to call one on. Addressing a component you hold no reference to is what an\n * external store is for.\n *\n * Underneath it is the wire protocol. A partial navigation sends only the\n * segment that changed — see the X-RSC-Segments headers — so there is nothing\n * for a root to re-render with even if it held the state. Next.js keeps its\n * router in useState and derives every segment from it; that is the same trade\n * in the other direction.\n *\n * What it costs: React pins an external store's updates to synchronous\n * priority, because a store cannot be safely time-sliced. Synchronous is never\n * a transition, and anything that only runs for one — React's <ViewTransition>\n * among them — never ran for a navigation.\n *\n * Which is why SegmentBoundary does not read this with useSyncExternalStore\n * any more. The store still does the addressing, which is the part only it can\n * do; the boundary copies into state, so the render is a transition. See the\n * view transitions guide.\n */\n\ntype Tree = unknown;\ntype Listener = () => void;\n\ninterface Entry {\n key: string;\n /**\n * The key React mounts this page under, when it is not `key`.\n *\n * `key` is what a navigation files the page under - its path and query, so\n * Back to ?q=a restores that page and not ?q=b. The identity is what keeps\n * it mounted, and it has to survive two things that are not a new page: a\n * page loaded with a query, which the server rendered under its pathname\n * alone (the shell was frozen that way), and a replace to the same path with\n * a new query - the first message of a chat - which leaves nothing to go\n * back to. A new identity is a remount, and a remount shows every Suspense\n * fallback in the page: a skeleton over the chat, on every reply.\n */\n identity?: string;\n tree: Tree;\n /**\n * When this tree arrived, so a link can decide whether it is still worth\n * revealing. The back button never asks — it means \"the page I was on\",\n * however long ago that was.\n */\n at: number;\n /**\n * Its place in the order things happened, for the question \"was this\n * here before the mutation?\" - which a clock answers wrongly for a seed\n * and a write in the same millisecond, and a test hit exactly that.\n */\n seq: number;\n /**\n * Rendered before the click, hidden, on the strength of a touch or a\n * settled hover - see prerenderSegment. Outside the retention window: it\n * is a guess, and a guess must not evict a page the visitor was on. One\n * per depth; the next guess replaces it, and a navigation to anything\n * else drops it.\n */\n speculative?: boolean;\n}\n\n/**\n * Immutable: useSyncExternalStore compares snapshots by identity, so a new\n * object per read reads as \"changed every render\" and loops forever. Every\n * mutation replaces this wholesale; nothing edits one in place.\n */\ninterface DepthState {\n readonly entries: readonly Entry[];\n readonly activeKey: string;\n /** Most recently shown last; eviction takes from the front. */\n readonly order: readonly string[];\n}\n\n/** Pages kept alive per boundary. Four covers ordinary back-and-forth. */\nexport const RETENTION = 4;\n\nconst depths = new Map<number, DepthState>();\n/** A counter every entry takes a number from, in order. */\nlet tick = 0;\n/** The number the last mutation took: everything held before it is wrong. */\nlet invalidatedAt = 0;\nconst listeners = new Map<number, Set<Listener>>();\n\nfunction notify(depth: number): void {\n for (const listener of listeners.get(depth) ?? []) listener();\n}\n\nexport function subscribeToSegment(\n depth: number,\n listener: Listener,\n): () => void {\n let set = listeners.get(depth);\n\n if (!set) {\n set = new Set();\n listeners.set(depth, set);\n }\n\n set.add(listener);\n\n return () => {\n set!.delete(listener);\n if (set!.size === 0) listeners.delete(depth);\n };\n}\n\n/** Everything a boundary at this depth needs to render, or null for \"use children\". */\nexport function getSegmentState(depth: number): DepthState | null {\n return depths.get(depth) ?? null;\n}\n\n/** Apply the retention window to a candidate state. */\nfunction retain(\n entries: readonly Entry[],\n order: readonly string[],\n activeKey: string,\n): DepthState {\n const kept = order.slice(-RETENTION);\n\n return {\n entries: entries.filter((entry) => kept.includes(entry.key) || entry.speculative),\n order: kept,\n activeKey,\n };\n}\n\nfunction put(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n // The same page again keeps the identity it is mounted under.\n const kept = identity ?? state?.entries.find((entry) => entry.key === key)?.identity;\n const entries = [\n ...(state?.entries ?? []).filter((entry) => entry.key !== key),\n { key, tree, at: Date.now(), seq: ++tick, ...(kept !== undefined && kept !== key ? { identity: kept } : {}) },\n ];\n const order = [...(state?.order ?? []).filter((k) => k !== key), key];\n\n depths.set(depth, retain(entries, order, key));\n}\n\n/**\n * Show `tree` at `depth` for `key`, retaining what was there.\n *\n * Deeper segments belonged to the page being replaced; leaving them would\n * render the previous page inside the new one.\n */\nexport function setSegment(depth: number, key: string, tree: Tree, inPlaceOf?: string | null): void {\n // A guess about another page was wrong; the one about this page, if there\n // was one, is replaced by put() below - with the same tree, when the\n // prerender and the navigation read the same decoded payload, which is\n // what makes the update a reveal rather than a render.\n dropSpeculative(depth, key);\n\n // A replace to the same path with a new query: the page it replaces is gone\n // from history, so this is that page, moved - not a new one to mount beside\n // it. It takes the old entry's identity, and the old entry goes.\n const state = depths.get(depth);\n const replaced =\n inPlaceOf && inPlaceOf !== key && !state?.entries.some((entry) => entry.key === key)\n ? state?.entries.find((entry) => entry.key === inPlaceOf)\n : undefined;\n\n if (replaced && state) {\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => entry !== replaced),\n order: state.order.filter((k) => k !== replaced.key),\n });\n }\n\n put(depth, key, tree, replaced ? (replaced.identity ?? replaced.key) : undefined);\n\n const stale = [...depths.keys()].filter((d) => d > depth);\n for (const d of stale) depths.delete(d);\n\n notify(depth);\n for (const d of stale) notify(d);\n}\n\nfunction dropSpeculative(depth: number, except?: string): void {\n const state = depths.get(depth);\n\n if (!state?.entries.some((entry) => entry.speculative && entry.key !== except)) return;\n\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => !entry.speculative || entry.key === except),\n });\n}\n\n/**\n * Render a page hidden at `depth`, before any navigation to it.\n *\n * The click then finds the work done: setSegment with the same tree is a\n * bail-out for React - same element, same props - and the Activity flips\n * from hidden to visible. What was 87 ms of rendering on a phone, after\n * the tap, is paid before the finger lifts, at idle priority, yielding to\n * the scroll. Never changes what is showing, never counts against\n * retention, and a page already held needs nothing.\n */\nexport function prerenderSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n // Nothing at this depth yet: the boundary is still showing the server's\n // children, and it has no page key to keep them under. A guess would take\n // the store over with no active entry to show. seedSegment runs on mount,\n // so this is the gap between hydration and that effect; the click will\n // render.\n if (!state) return;\n\n if (state.entries.some((entry) => entry.key === key)) return;\n\n depths.set(depth, {\n ...state,\n entries: [\n ...state.entries.filter((entry) => !entry.speculative),\n { key, tree, at: Date.now(), seq: ++tick, speculative: true },\n ],\n });\n\n notify(depth);\n}\n\n/** Whether a page is rendered hidden at `depth`, ahead of a navigation to it. */\nexport function isPrerendered(depth: number, key: string): boolean {\n return depths.get(depth)?.entries.some((entry) => entry.key === key && entry.speculative) ?? false;\n}\n\n/**\n * Give the page on screen at `depth` a new tree, under the key it has.\n *\n * For revalidate(\"all\"): the whole document rendered again, in place. The\n * root hands its layout the new tree, the layout hands its boundary new\n * children, and a boundary that holds state would otherwise keep showing\n * the store's tree and drop the new one on the floor - or, cleared first,\n * re-key its Activity to the current url and remount everything under it.\n * Neither. The entry that is showing takes the new tree and keeps its key,\n * so React reconciles the page in place, and the boundary below gets its\n * new children the same way.\n */\nexport function replaceActive(depth: number, tree: Tree): void {\n const state = depths.get(depth);\n\n if (!state) return;\n\n const active = state.entries.find((entry) => entry.key === state.activeKey);\n\n if (!active || active.tree === tree) return;\n\n // The tree changes; when the entry arrived does not. A layout's entry is\n // keyed by the page it was seeded with - \"/\" for a document loaded at\n // home - and stays active through every navigation below it. Stamped\n // with the re-render's time it read as held since the mutation, and a\n // tap on the brand link after \"Add to cart\" revealed it: the url went\n // to \"/\" and the product stayed, because the tree under that key was\n // now the product's document. See dropHidden and isHeld.\n depths.set(depth, {\n ...state,\n entries: state.entries.map((entry) => (entry === active ? { ...entry, tree } : entry)),\n });\n notify(depth);\n}\n\n/**\n * Record the children the server rendered, so the page you arrived on can be\n * returned to later. Never changes what is showing.\n */\nexport function seedSegment(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n\n if (state?.entries.some((entry) => entry.key === key)) return;\n\n if (!state) {\n put(depth, key, tree, identity);\n notify(depth);\n\n return;\n }\n\n // Older than whatever is showing, so it goes to the front of the eviction\n // order — and crucially does not become the active page.\n depths.set(\n depth,\n retain(\n [...state.entries, { key, tree, at: Date.now(), seq: ++tick, ...(identity !== undefined && identity !== key ? { identity } : {}) }],\n [key, ...state.order.filter((k) => k !== key)],\n state.activeKey,\n ),\n );\n\n notify(depth);\n}\n\n/**\n * Reveal a page the boundaries are still holding, without asking the server.\n *\n * Restoring is anchored on the deepest boundary that can show the page. Deeper\n * ones than that belonged to the page being left — a section with its own\n * layout adds a boundary the page you are going back to never had — so they\n * are dropped, exactly as setSegment drops them. Requiring every boundary to\n * hold the key instead made any such page refuse to restore.\n *\n * Shallower boundaries need no key of their own: their trees contain the\n * deeper boundary, so they delegate to whatever it is showing. One that does\n * hold the key is switched to it, since that is a real change at its level.\n */\n/**\n * Whether a link to `key` would be answered by revealing a held page.\n *\n * The question restoreSegments answers, asked without acting on it: a\n * prefetch of a page the boundaries still hold is a request for nothing -\n * a navigation would reveal it. The page just left is the usual case, one\n * wasted payload per navigation.\n */\nexport function isHeld(key: string, maxAge?: number): boolean {\n const ages = [...depths.values()].flatMap((state) =>\n state.entries.filter((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt).map((entry) => entry.at),\n );\n\n if (ages.length === 0) return false;\n if (maxAge === undefined) return true;\n\n return Date.now() - Math.min(...ages) < maxAge;\n}\n\n/**\n * Drop every page held behind the one on screen.\n *\n * After a mutation: a page kept for the back button holds the data from\n * before it, and revealing it would show a row that is gone, a name that\n * changed. The page on screen stays - it was re-rendered by the action, or\n * is about to be.\n */\nexport function dropHidden(): void {\n // And the ones that stay - the active entry at each depth - are from\n // before it too. A layout's entry is keyed by the page it was seeded\n // with, and revealing that key later shows the page inside it as it was\n // then. Nothing seeded before this moment is revealed again.\n invalidatedAt = ++tick;\n\n for (const [depth, state] of depths) {\n if (state.entries.length <= 1 && !state.entries.some((entry) => entry.speculative)) continue;\n\n depths.set(depth, {\n entries: state.entries.filter((entry) => entry.key === state.activeKey),\n order: state.order.filter((key) => key === state.activeKey),\n activeKey: state.activeKey,\n });\n notify(depth);\n }\n}\n\n/**\n * Reveal a page still being held, if it is worth revealing.\n *\n * `maxAge` is what a link passes and the back button does not. Going back is\n * unambiguous — it names a moment, and the page from that moment is the right\n * answer however old. A link says \"go here\", and answering it with a tree from\n * twenty minutes ago is stale data presented as fresh, which is the objection\n * this design started with. Recent enough, and it is the same page you were\n * just on, with the form you were filling in still filled in.\n */\nexport function restoreSegments(key: string, maxAge?: number): boolean {\n // A guess is not a held page: revealing it would be showing prefetched\n // data as the page the visitor was on. The navigation takes the\n // prerendered tree through setSegment instead, where it is a reveal too.\n // Nor is a page from before a mutation - see dropHidden.\n const holding = [...depths.keys()].filter((d) =>\n depths.get(d)!.entries.some((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt),\n );\n\n if (holding.length === 0) return false;\n\n if (maxAge !== undefined) {\n const ages = holding.flatMap((d) =>\n depths\n .get(d)!\n .entries.filter((entry) => entry.key === key)\n .map((entry) => entry.at),\n );\n\n // The oldest layer decides: revealing a fresh page under a stale layout\n // would be a chain nobody rendered together.\n // >= rather than >, so a window of 0 means never rather than \"only within\n // the same millisecond\".\n if (Date.now() - Math.min(...ages) >= maxAge) return false;\n }\n\n const anchor = Math.max(...holding);\n\n for (const d of [...depths.keys()].filter((d) => d > anchor)) {\n depths.delete(d);\n notify(d);\n }\n\n for (const d of holding) {\n dropSpeculative(d);\n\n const state = depths.get(d)!;\n\n depths.set(\n d,\n retain(\n state.entries,\n [...state.order.filter((k) => k !== key), key],\n key,\n ),\n );\n notify(d);\n }\n\n return true;\n}\n\n/**\n * Drop everything, so boundaries fall back to their server-given children.\n *\n * A deployment invalidates them all: a segment from the previous build has no\n * claim on being correct for this one.\n */\nexport function clearSegments(): void {\n const all = [...depths.keys()];\n depths.clear();\n for (const depth of all) notify(depth);\n}\n\n/**\n * Whether a navigation has happened in this document.\n *\n * The first commit after hydration is the boundary taking over its\n * server-rendered children - the same page, re-keyed for retention. A view\n * transition for that commit fades the page into itself: the blank-then-\n * content a first load or a reload showed. Inertia transitions on visits and\n * never on load; so does this. The router notes the first navigation before\n * it updates a segment, and the boundary animates from then on.\n */\nlet navigated = false;\n\nexport function noteNavigation(): void {\n navigated = true;\n}\n\nexport function navigatedOnce(): boolean {\n return navigated;\n}\n"]}
1
+ {"version":3,"file":"segmentStore.js","sourceRoot":"","sources":["../../src/js/segmentStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAuDH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAE3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;AAC7C,2DAA2D;AAC3D,IAAI,IAAI,GAAG,CAAC,CAAC;AACb,6EAA6E;AAC7E,IAAI,aAAa,GAAG,CAAC,CAAC;AACtB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEnD,SAAS,MAAM,CAAC,KAAa;IAC3B,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,QAAkB;IAElB,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAE/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;QAChB,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAElB,OAAO,GAAG,EAAE;QACV,GAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtB,IAAI,GAAI,CAAC,IAAI,KAAK,CAAC;YAAE,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACnC,CAAC;AAED,uDAAuD;AACvD,SAAS,MAAM,CACb,OAAyB,EACzB,KAAwB,EACxB,SAAiB;IAEjB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC;IAErC,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC;QACjF,KAAK,EAAE,IAAI;QACX,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,GAAG,CAAC,KAAa,EAAE,GAAW,EAAE,IAAU,EAAE,QAAiB;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,8DAA8D;IAC9D,MAAM,IAAI,GAAG,QAAQ,IAAI,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,QAAQ,CAAC;IACrF,MAAM,OAAO,GAAG;QACd,GAAG,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAC9D,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;KAC9G,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAEtE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CACxB,KAAa,EACb,GAAW,EACX,IAAU,EACV,SAAyB,EACzB,aAAuB;IAEvB,0EAA0E;IAC1E,qEAAqE;IACrE,uEAAuE;IACvE,uDAAuD;IACvD,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE5B,0EAA0E;IAC1E,0EAA0E;IAC1E,sEAAsE;IACtE,yEAAyE;IACzE,4EAA4E;IAC5E,6DAA6D;IAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,QAAQ,GACZ,SAAS,IAAI,SAAS,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAClF,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC;QACzD,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,CACR,KAAK,EACL,aAAa;YACX,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;YACtI,CAAC,CAAC;gBACE,GAAG,KAAK;gBACR,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC;gBAC5D,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,GAAG,CAAC;aACrD,CACN,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAElF,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;IAC1D,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAExC,MAAM,CAAC,KAAK,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,eAAe,CAAC,KAAa,EAAE,MAAe;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC;QAAE,OAAO;IAEvF,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;QAChB,GAAG,KAAK;QACR,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC;KACrF,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,GAAW,EAAE,IAAU;IACrE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,wEAAwE;IACxE,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,UAAU;IACV,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAAE,OAAO;IAE7D,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;QAChB,GAAG,KAAK;QACR,OAAO,EAAE;YACP,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;YACtD,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;SAC9D;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CAAC,CAAC;AAChB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,GAAW;IACtD,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC;AACrG,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,IAAU;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAE5E,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO;IAE5C,yEAAyE;IACzE,sEAAsE;IACtE,qEAAqE;IACrE,sEAAsE;IACtE,sEAAsE;IACtE,qEAAqE;IACrE,yDAAyD;IACzD,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;QAChB,GAAG,KAAK;QACR,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;KACvF,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,CAAC,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,GAAW,EAAE,IAAU,EAAE,QAAiB;IACnF,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;QAAE,OAAO;IAE9D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEd,OAAO;IACT,CAAC;IAED,0EAA0E;IAC1E,yDAAyD;IACzD,MAAM,CAAC,GAAG,CACR,KAAK,EACL,MAAM,CACJ,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACnI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,EAC9C,KAAK,CAAC,SAAS,CAChB,CACF,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,GAAW,EAAE,MAAe;IACjD,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAClD,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAC/H,CAAC;IAEF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAEtC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU;IACxB,qEAAqE;IACrE,qEAAqE;IACrE,wEAAwE;IACxE,6DAA6D;IAC7D,aAAa,GAAG,EAAE,IAAI,CAAC;IAEvB,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC;YAAE,SAAS;QAE7F,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;YACvE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;YAC3D,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,MAAe;IAC1D,uEAAuE;IACvE,gEAAgE;IAChE,yEAAyE;IACzE,yDAAyD;IACzD,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,GAAG,aAAa,CAAC,CAC7G,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACjC,MAAM;aACH,GAAG,CAAC,CAAC,CAAE;aACP,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC;aAC5C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAC5B,CAAC;QAEF,wEAAwE;QACxE,6CAA6C;QAC7C,0EAA0E;QAC1E,yBAAyB;QACzB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,MAAM;YAAE,OAAO,KAAK,CAAC;IAC7D,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAEpC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;QAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjB,MAAM,CAAC,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,eAAe,CAAC,CAAC,CAAC,CAAC;QAEnB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;QAE7B,MAAM,CAAC,GAAG,CACR,CAAC,EACD,MAAM,CACJ,KAAK,CAAC,OAAO,EACb,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,EAC9C,GAAG,CACJ,CACF,CAAC;QACF,MAAM,CAAC,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,GAAG;QAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;GASG;AACH,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,MAAM,UAAU,cAAc;IAC5B,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["/**\n * What each segment boundary is showing, and what it is keeping alive behind it.\n *\n * A navigation replaces one segment. Keeping the previous one mounted — hidden,\n * not unmounted — is what lets going back restore it with its client state:\n * the half-typed form, the open disclosure, the scrolled list. Unmounting\n * throws all of that away, which is what replacing the root used to do.\n *\n * Entries are keyed by page (the URL, or its intercept variant), so a boundary\n * can hold several and reveal one. Empty is meaningful: a boundary with nothing\n * stored renders the children the server gave it.\n *\n * A store rather than state, and not a preference — three things rule state out.\n * A boundary is inserted between every layout level, so there are several and a\n * navigation targets one by depth; they are separated by server components, so\n * no setter can be threaded down to them, because a function does not cross\n * that boundary; and navigate.ts is a plain module with no component instance\n * to call one on. Addressing a component you hold no reference to is what an\n * external store is for.\n *\n * Underneath it is the wire protocol. A partial navigation sends only the\n * segment that changed — see the X-RSC-Segments headers — so there is nothing\n * for a root to re-render with even if it held the state. Next.js keeps its\n * router in useState and derives every segment from it; that is the same trade\n * in the other direction.\n *\n * What it costs: React pins an external store's updates to synchronous\n * priority, because a store cannot be safely time-sliced. Synchronous is never\n * a transition, and anything that only runs for one — React's <ViewTransition>\n * among them — never ran for a navigation.\n *\n * Which is why SegmentBoundary does not read this with useSyncExternalStore\n * any more. The store still does the addressing, which is the part only it can\n * do; the boundary copies into state, so the render is a transition. See the\n * view transitions guide.\n */\n\ntype Tree = unknown;\ntype Listener = () => void;\n\ninterface Entry {\n key: string;\n /**\n * The key React mounts this page under, when it is not `key`.\n *\n * `key` is what a navigation files the page under - its path and query, so\n * Back to ?q=a restores that page and not ?q=b. The identity is what keeps\n * it mounted, and it has to survive two things that are not a new page: a\n * page loaded with a query, which the server rendered under its pathname\n * alone (the shell was frozen that way), and a replace to the same path with\n * a new query - the first message of a chat - which leaves nothing to go\n * back to. A new identity is a remount, and a remount shows every Suspense\n * fallback in the page: a skeleton over the chat, on every reply.\n */\n identity?: string;\n tree: Tree;\n /**\n * When this tree arrived, so a link can decide whether it is still worth\n * revealing. The back button never asks — it means \"the page I was on\",\n * however long ago that was.\n */\n at: number;\n /**\n * Its place in the order things happened, for the question \"was this\n * here before the mutation?\" - which a clock answers wrongly for a seed\n * and a write in the same millisecond, and a test hit exactly that.\n */\n seq: number;\n /**\n * Rendered before the click, hidden, on the strength of a touch or a\n * settled hover - see prerenderSegment. Outside the retention window: it\n * is a guess, and a guess must not evict a page the visitor was on. One\n * per depth; the next guess replaces it, and a navigation to anything\n * else drops it.\n */\n speculative?: boolean;\n}\n\n/**\n * Immutable: useSyncExternalStore compares snapshots by identity, so a new\n * object per read reads as \"changed every render\" and loops forever. Every\n * mutation replaces this wholesale; nothing edits one in place.\n */\ninterface DepthState {\n readonly entries: readonly Entry[];\n readonly activeKey: string;\n /** Most recently shown last; eviction takes from the front. */\n readonly order: readonly string[];\n}\n\n/** Pages kept alive per boundary. Four covers ordinary back-and-forth. */\nexport const RETENTION = 4;\n\nconst depths = new Map<number, DepthState>();\n/** A counter every entry takes a number from, in order. */\nlet tick = 0;\n/** The number the last mutation took: everything held before it is wrong. */\nlet invalidatedAt = 0;\nconst listeners = new Map<number, Set<Listener>>();\n\nfunction notify(depth: number): void {\n for (const listener of listeners.get(depth) ?? []) listener();\n}\n\nexport function subscribeToSegment(\n depth: number,\n listener: Listener,\n): () => void {\n let set = listeners.get(depth);\n\n if (!set) {\n set = new Set();\n listeners.set(depth, set);\n }\n\n set.add(listener);\n\n return () => {\n set!.delete(listener);\n if (set!.size === 0) listeners.delete(depth);\n };\n}\n\n/** Everything a boundary at this depth needs to render, or null for \"use children\". */\nexport function getSegmentState(depth: number): DepthState | null {\n return depths.get(depth) ?? null;\n}\n\n/** Apply the retention window to a candidate state. */\nfunction retain(\n entries: readonly Entry[],\n order: readonly string[],\n activeKey: string,\n): DepthState {\n const kept = order.slice(-RETENTION);\n\n return {\n entries: entries.filter((entry) => kept.includes(entry.key) || entry.speculative),\n order: kept,\n activeKey,\n };\n}\n\nfunction put(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n // The same page again keeps the identity it is mounted under.\n const kept = identity ?? state?.entries.find((entry) => entry.key === key)?.identity;\n const entries = [\n ...(state?.entries ?? []).filter((entry) => entry.key !== key),\n { key, tree, at: Date.now(), seq: ++tick, ...(kept !== undefined && kept !== key ? { identity: kept } : {}) },\n ];\n const order = [...(state?.order ?? []).filter((k) => k !== key), key];\n\n depths.set(depth, retain(entries, order, key));\n}\n\n/**\n * Show `tree` at `depth` for `key`, retaining what was there.\n *\n * Deeper segments belonged to the page being replaced; leaving them would\n * render the previous page inside the new one.\n */\nexport function setSegment(\n depth: number,\n key: string,\n tree: Tree,\n inPlaceOf?: string | null,\n keepsPrevious?: boolean,\n): void {\n // A guess about another page was wrong; the one about this page, if there\n // was one, is replaced by put() below - with the same tree, when the\n // prerender and the navigation read the same decoded payload, which is\n // what makes the update a reveal rather than a render.\n dropSpeculative(depth, key);\n\n // The same path with a new query is the page on screen, moved - not a new\n // one to mount beside it, which would show every fallback in the page. It\n // takes the old entry's identity, so React updates the page it has. A\n // replace has left that entry nothing to go back to, and it goes. A push\n // keeps it for Back, under an identity of its own: mounted again behind the\n // page, where its tree is already decoded and nothing waits.\n const state = depths.get(depth);\n const replaced =\n inPlaceOf && inPlaceOf !== key && !state?.entries.some((entry) => entry.key === key)\n ? state?.entries.find((entry) => entry.key === inPlaceOf)\n : undefined;\n\n if (replaced && state) {\n depths.set(\n depth,\n keepsPrevious\n ? { ...state, entries: state.entries.map((entry) => (entry === replaced ? { ...entry, identity: `${entry.key}#${++tick}` } : entry)) }\n : {\n ...state,\n entries: state.entries.filter((entry) => entry !== replaced),\n order: state.order.filter((k) => k !== replaced.key),\n },\n );\n }\n\n put(depth, key, tree, replaced ? (replaced.identity ?? replaced.key) : undefined);\n\n const stale = [...depths.keys()].filter((d) => d > depth);\n for (const d of stale) depths.delete(d);\n\n notify(depth);\n for (const d of stale) notify(d);\n}\n\nfunction dropSpeculative(depth: number, except?: string): void {\n const state = depths.get(depth);\n\n if (!state?.entries.some((entry) => entry.speculative && entry.key !== except)) return;\n\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => !entry.speculative || entry.key === except),\n });\n}\n\n/**\n * Render a page hidden at `depth`, before any navigation to it.\n *\n * The click then finds the work done: setSegment with the same tree is a\n * bail-out for React - same element, same props - and the Activity flips\n * from hidden to visible. What was 87 ms of rendering on a phone, after\n * the tap, is paid before the finger lifts, at idle priority, yielding to\n * the scroll. Never changes what is showing, never counts against\n * retention, and a page already held needs nothing.\n */\nexport function prerenderSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n // Nothing at this depth yet: the boundary is still showing the server's\n // children, and it has no page key to keep them under. A guess would take\n // the store over with no active entry to show. seedSegment runs on mount,\n // so this is the gap between hydration and that effect; the click will\n // render.\n if (!state) return;\n\n if (state.entries.some((entry) => entry.key === key)) return;\n\n depths.set(depth, {\n ...state,\n entries: [\n ...state.entries.filter((entry) => !entry.speculative),\n { key, tree, at: Date.now(), seq: ++tick, speculative: true },\n ],\n });\n\n notify(depth);\n}\n\n/** Whether a page is rendered hidden at `depth`, ahead of a navigation to it. */\nexport function isPrerendered(depth: number, key: string): boolean {\n return depths.get(depth)?.entries.some((entry) => entry.key === key && entry.speculative) ?? false;\n}\n\n/**\n * Give the page on screen at `depth` a new tree, under the key it has.\n *\n * For revalidate(\"all\"): the whole document rendered again, in place. The\n * root hands its layout the new tree, the layout hands its boundary new\n * children, and a boundary that holds state would otherwise keep showing\n * the store's tree and drop the new one on the floor - or, cleared first,\n * re-key its Activity to the current url and remount everything under it.\n * Neither. The entry that is showing takes the new tree and keeps its key,\n * so React reconciles the page in place, and the boundary below gets its\n * new children the same way.\n */\nexport function replaceActive(depth: number, tree: Tree): void {\n const state = depths.get(depth);\n\n if (!state) return;\n\n const active = state.entries.find((entry) => entry.key === state.activeKey);\n\n if (!active || active.tree === tree) return;\n\n // The tree changes; when the entry arrived does not. A layout's entry is\n // keyed by the page it was seeded with - \"/\" for a document loaded at\n // home - and stays active through every navigation below it. Stamped\n // with the re-render's time it read as held since the mutation, and a\n // tap on the brand link after \"Add to cart\" revealed it: the url went\n // to \"/\" and the product stayed, because the tree under that key was\n // now the product's document. See dropHidden and isHeld.\n depths.set(depth, {\n ...state,\n entries: state.entries.map((entry) => (entry === active ? { ...entry, tree } : entry)),\n });\n notify(depth);\n}\n\n/**\n * Record the children the server rendered, so the page you arrived on can be\n * returned to later. Never changes what is showing.\n */\nexport function seedSegment(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n\n if (state?.entries.some((entry) => entry.key === key)) return;\n\n if (!state) {\n put(depth, key, tree, identity);\n notify(depth);\n\n return;\n }\n\n // Older than whatever is showing, so it goes to the front of the eviction\n // order — and crucially does not become the active page.\n depths.set(\n depth,\n retain(\n [...state.entries, { key, tree, at: Date.now(), seq: ++tick, ...(identity !== undefined && identity !== key ? { identity } : {}) }],\n [key, ...state.order.filter((k) => k !== key)],\n state.activeKey,\n ),\n );\n\n notify(depth);\n}\n\n/**\n * Reveal a page the boundaries are still holding, without asking the server.\n *\n * Restoring is anchored on the deepest boundary that can show the page. Deeper\n * ones than that belonged to the page being left — a section with its own\n * layout adds a boundary the page you are going back to never had — so they\n * are dropped, exactly as setSegment drops them. Requiring every boundary to\n * hold the key instead made any such page refuse to restore.\n *\n * Shallower boundaries need no key of their own: their trees contain the\n * deeper boundary, so they delegate to whatever it is showing. One that does\n * hold the key is switched to it, since that is a real change at its level.\n */\n/**\n * Whether a link to `key` would be answered by revealing a held page.\n *\n * The question restoreSegments answers, asked without acting on it: a\n * prefetch of a page the boundaries still hold is a request for nothing -\n * a navigation would reveal it. The page just left is the usual case, one\n * wasted payload per navigation.\n */\nexport function isHeld(key: string, maxAge?: number): boolean {\n const ages = [...depths.values()].flatMap((state) =>\n state.entries.filter((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt).map((entry) => entry.at),\n );\n\n if (ages.length === 0) return false;\n if (maxAge === undefined) return true;\n\n return Date.now() - Math.min(...ages) < maxAge;\n}\n\n/**\n * Drop every page held behind the one on screen.\n *\n * After a mutation: a page kept for the back button holds the data from\n * before it, and revealing it would show a row that is gone, a name that\n * changed. The page on screen stays - it was re-rendered by the action, or\n * is about to be.\n */\nexport function dropHidden(): void {\n // And the ones that stay - the active entry at each depth - are from\n // before it too. A layout's entry is keyed by the page it was seeded\n // with, and revealing that key later shows the page inside it as it was\n // then. Nothing seeded before this moment is revealed again.\n invalidatedAt = ++tick;\n\n for (const [depth, state] of depths) {\n if (state.entries.length <= 1 && !state.entries.some((entry) => entry.speculative)) continue;\n\n depths.set(depth, {\n entries: state.entries.filter((entry) => entry.key === state.activeKey),\n order: state.order.filter((key) => key === state.activeKey),\n activeKey: state.activeKey,\n });\n notify(depth);\n }\n}\n\n/**\n * Reveal a page still being held, if it is worth revealing.\n *\n * `maxAge` is what a link passes and the back button does not. Going back is\n * unambiguous — it names a moment, and the page from that moment is the right\n * answer however old. A link says \"go here\", and answering it with a tree from\n * twenty minutes ago is stale data presented as fresh, which is the objection\n * this design started with. Recent enough, and it is the same page you were\n * just on, with the form you were filling in still filled in.\n */\nexport function restoreSegments(key: string, maxAge?: number): boolean {\n // A guess is not a held page: revealing it would be showing prefetched\n // data as the page the visitor was on. The navigation takes the\n // prerendered tree through setSegment instead, where it is a reveal too.\n // Nor is a page from before a mutation - see dropHidden.\n const holding = [...depths.keys()].filter((d) =>\n depths.get(d)!.entries.some((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt),\n );\n\n if (holding.length === 0) return false;\n\n if (maxAge !== undefined) {\n const ages = holding.flatMap((d) =>\n depths\n .get(d)!\n .entries.filter((entry) => entry.key === key)\n .map((entry) => entry.at),\n );\n\n // The oldest layer decides: revealing a fresh page under a stale layout\n // would be a chain nobody rendered together.\n // >= rather than >, so a window of 0 means never rather than \"only within\n // the same millisecond\".\n if (Date.now() - Math.min(...ages) >= maxAge) return false;\n }\n\n const anchor = Math.max(...holding);\n\n for (const d of [...depths.keys()].filter((d) => d > anchor)) {\n depths.delete(d);\n notify(d);\n }\n\n for (const d of holding) {\n dropSpeculative(d);\n\n const state = depths.get(d)!;\n\n depths.set(\n d,\n retain(\n state.entries,\n [...state.order.filter((k) => k !== key), key],\n key,\n ),\n );\n notify(d);\n }\n\n return true;\n}\n\n/**\n * Drop everything, so boundaries fall back to their server-given children.\n *\n * A deployment invalidates them all: a segment from the previous build has no\n * claim on being correct for this one.\n */\nexport function clearSegments(): void {\n const all = [...depths.keys()];\n depths.clear();\n for (const depth of all) notify(depth);\n}\n\n/**\n * Whether a navigation has happened in this document.\n *\n * The first commit after hydration is the boundary taking over its\n * server-rendered children - the same page, re-keyed for retention. A view\n * transition for that commit fades the page into itself: the blank-then-\n * content a first load or a reload showed. Inertia transitions on visits and\n * never on load; so does this. The router notes the first navigation before\n * it updates a segment, and the boundary animates from then on.\n */\nlet navigated = false;\n\nexport function noteNavigation(): void {\n navigated = true;\n}\n\nexport function navigatedOnce(): boolean {\n return navigated;\n}\n"]}
package/dist/request.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type { ServedRequest } from "./served.js";
1
2
  /** What a host can supply: a real Request, or the parts of one. */
2
3
  export type RequestLike = Request | {
3
4
  url: string;
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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","sourcesContent":["// Reading the request from inside a render.\n//\n// import { headers, cookies } from '@rsc-kit/core/request'\n//\n// export default async function middleware() {\n// const locale = cookies().get('locale')?.value ?? negotiate(headers().get('accept-language'))\n// if (!locale) redirect('/en')\n// }\n//\n// Server components have no arguments beyond their props, and middleware has\n// none at all, so without this an app on a JavaScript host cannot see a header\n// — no locale negotiation, no subdomain, no cookie. The Laravel host escaped\n// that through rpc(), because PHP has the request; this is the same thing for\n// everyone else.\n//\n// Read-only on purpose. Setting a cookie means writing a response header, and\n// by the time a component renders the shell may already have been flushed — an\n// API that appears to set one and silently does not is worse than not having\n// it. Set them in the host, which owns the response.\n//\n// Asynchronous on purpose too, and not for ergonomics. A build has no request,\n// so a read there suspends and never settles — which is the same thing the\n// prerender probe does to a host call. Anything still waiting when the probe's\n// budget expires becomes a fallback in the frozen shell, so a read inside a\n// Suspense boundary leaves the shell frozen and makes only that boundary\n// dynamic. Reading synchronously could only mark the whole route dynamic,\n// because there would be nothing to suspend on.\n//\n// Scoped to the request, on the same store cache() uses. Two requests in\n// flight cannot see each other's headers.\n\nimport { isCrawler } from \"./crawler.js\";\nimport { resolveScope } from \"./revalidate.js\";\n\n/** What a host can supply: a real Request, or the parts of one. */\nexport type RequestLike =\n Request | { url: string; headers: Record<string, string> } | null;\n\ninterface Slot {\n /** False during a build: there is nothing to answer with. */\n request: boolean;\n url: string | null;\n /**\n * Held as Headers rather than as a Request.\n *\n * `new Request(url, { headers })` drops Cookie: a spec-compliant Headers\n * built with the \"request\" guard refuses the forbidden header names, and\n * Cookie is one of them. `new Headers()` has no guard and keeps it. Bun\n * happens to allow both, which is why rebuilding a Request looked fine until\n * it ran anywhere stricter — and what it loses is every cookie, silently.\n */\n headers: Headers;\n original: Request | null;\n /**\n * Whether anything asked. Only for the build's report — the classification\n * comes from the suspension, not from this.\n */\n read: boolean;\n /**\n * What read it, in the order they did.\n *\n * Only the name of the accessor — `cookies()`, `headers()` — which is enough\n * for the build to say why a page could not be frozen. Without it the answer\n * is \"something in this page reached for the request\", and finding which is\n * the part that takes an afternoon.\n */\n readBy: string[];\n /**\n * The same reads with the component that made each one - `cookies() in\n * RootLayout` - taken from the stack at the moment of the read, which is\n * still the component's own call: an accessor runs synchronously up to\n * the point it suspends. Only the build reads this. \"Reads the request\" is\n * a category; this is the line to open.\n */\n readWhere: string[];\n /**\n * Reads the server could not answer and React caught at a boundary - the\n * fallback is what got stored - with the component that made each:\n * `useSearchParams() in Query`. Noted by the SSR entry, read by the build,\n * which attaches them to the route so a page stored as its own loading\n * screen says why.\n */\n fallbacks: string[];\n /**\n * For a read made inside a cache()-wrapped helper: the components that\n * awaited that helper, first caller included. The helper runs once, so\n * the stack at the read names only whoever got there first; every later\n * awaiter is a cache hit that never reaches the accessor. The one above\n * every boundary is usually one of the later ones.\n */\n awaiters: Map<unknown, string[]>;\n /** The cache()-wrapped helper whose body is running, while it runs. */\n inHelper: unknown;\n /** readWhere entry -> the helper it was read inside. */\n readVia: Map<string, unknown>;\n /** Work to run once the answer is on its way - see after(). */\n after: (() => unknown)[];\n /** The props the page was rendered with - its params and searchParams - for a region rendered inside it to read. */\n pageProps?: Record<string, unknown>;\n}\n\nconst SCOPE = Symbol.for(\"@rsc-kit/core.request-scope\");\n\n/**\n * The accessors themselves and the plumbing under them: frames to walk past\n * on the way to the component that called.\n */\nconst NOT_A_CALLER = new Set([\n \"never\",\n // A thenable's own method: the read is named by what it was for.\n \"then\",\n \"cache\",\n \"noteAwaiter\",\n \"withHelper\",\n \"noteRequestRead\",\n \"recordRead\",\n \"caller\",\n \"slot\",\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n \"parseParams\",\n \"parseSearchParams\",\n \"parseBody\",\n \"get\",\n \"set\",\n \"has\",\n]);\n\n/** The accessors a component calls by name. One calling another is plumbing, not a second read. */\nconst ACCESSORS = new Set([\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n]);\n\n/**\n * The nearest named function above the accessor on the stack, and whether\n * another accessor sits between: `cookies()` reads through `headers()`, and\n * that inner read is not a second thing the component did.\n *\n * Read from a thrown-away Error: the one thing a build cannot otherwise learn\n * is which component reached for the request, and the stack knows. Function\n * names survive a server bundle, which is not minified, so this is\n * `RootLayout` and not a line number in a chunk. Internal names are walked\n * past; an anonymous frame is skipped rather than reported as `<anonymous>`.\n */\nfunction caller(own: string): { name: string | null; nested: boolean } {\n const stack = new Error().stack ?? \"\";\n let accessors = 0;\n let helper: string | null = null;\n\n for (const line of stack.split(\"\\n\")) {\n const match = /^\\s*at (?:async )?([^\\s(]+)/.exec(line);\n\n if (!match) continue;\n\n const name = match[1]!.split(\".\").pop()!;\n\n // A frame with no function name prints its location instead - `js:6054:8`\n // - which is not a name to report.\n if (!/^[\\w$]+$/.test(name)) continue;\n\n if (ACCESSORS.has(name)) accessors++;\n if (\n NOT_A_CALLER.has(name) ||\n name === \"<anonymous>\" ||\n name === \"Object\" ||\n name === \"Promise\"\n )\n continue;\n\n const nested = accessors > (ACCESSORS.has(own) ? 1 : 0);\n\n // A function that is not a component - getCurrentUser, wrapped in\n // cache() - is the shared helper the read lives in. Named, because with\n // cache() the read runs once, on whichever component called first, and\n // every other caller of the helper is invisible to the stack. The helper\n // is what they have in common.\n if (/^[a-z_$]/.test(name) && !/^use[A-Z]/.test(name)) {\n helper ??= name;\n\n continue;\n }\n\n return {\n name: helper && helper !== name ? `${helper} (from ${name})` : name,\n nested,\n };\n }\n\n return { name: helper, nested: accessors > (ACCESSORS.has(own) ? 1 : 0) };\n}\n\nfunction recordRead(store: Slot, by: string): void {\n if (!store.readBy.includes(by)) store.readBy.push(by);\n\n // Older stores, written by a bundle built before this field existed.\n store.readWhere ??= [];\n\n const { name, nested } = caller(by.replace(/\\(.*$/, \"\"));\n\n if (nested) return;\n\n const entry = name ? `${by} in ${name}` : by;\n\n if (!store.readWhere.includes(entry)) store.readWhere.push(entry);\n if (store.inHelper) (store.readVia ??= new Map()).set(entry, store.inHelper);\n}\n\nconst globals = globalThis as Record<symbol | string, unknown>;\n\nlet ready: Promise<void> | null = null;\n\ninterface Scope {\n getStore(): Slot | undefined;\n run<T>(store: Slot, fn: () => T): T;\n}\n\nfunction scope(): Scope | null {\n return (globals[SCOPE] as Scope | undefined) ?? null;\n}\n\nfunction slot(): Slot {\n const store = scope()?.getStore();\n\n if (!store) {\n throw new Error(\n \"No request in scope. headers() and cookies() are for a render — middleware, a layout, \" +\n \"a page — and there is nothing to read outside one.\",\n );\n }\n\n store.read = true;\n\n return store;\n}\n\n/**\n * The request's headers.\n *\n * Empty during a build, where there is no request: the page is marked as\n * needing one instead, and rendered on demand rather than frozen.\n */\nexport async function headers(): Promise<Headers> {\n const store = slot();\n\n return store.request ? store.headers : never(\"headers()\");\n}\n\n/** How a cookie should be written. The names browsers use. */\nexport interface CookieOptions {\n path?: string;\n domain?: string;\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n partitioned?: boolean;\n}\n\n/** One cookie as the request carried it: the shape Next's `cookies().get()` returns. */\nexport interface RequestCookie {\n name: string;\n value: string;\n}\n\n/**\n * The cookie jar, in the shape Next's `cookies()` has.\n *\n * `get()` returns `{ name, value }` rather than the string, because the guide\n * says \"the same names from `@rsc-kit/core/request`\" and a name that is the\n * same with a different return shape is the worst of both: ported code\n * reading `?.value` off a string got `undefined`, silently. `getAll()` is a\n * list for the same reason, and because a list composes where a record does\n * not.\n */\nexport interface Cookies {\n get(name: string): RequestCookie | undefined;\n has(name: string): boolean;\n getAll(): RequestCookie[];\n /**\n * Write one on the response.\n *\n * Only from a server action, which has a response of its own that has not\n * been sent. A render has already flushed its headers by the time a\n * component runs — that is what makes the first paint fast — so this throws\n * there rather than appearing to work.\n *\n * Either call shape Next takes: `set(name, value, options)` or\n * `set({ name, value, ...options })`.\n */\n set(name: string, value: string, options?: CookieOptions): void;\n set(cookie: RequestCookie & CookieOptions): void;\n /** Write one that expires immediately. Same rule about where. */\n delete(name: string, options?: CookieOptions): void;\n}\n\n/** Kept for the name it had when it could only read. */\nexport type ReadonlyCookies = Cookies;\n\n/**\n * The response being built, while it can still be changed.\n *\n * Open from the moment a request is picked up until the host constructs its\n * Response, and sealed the instant it does. Middleware runs inside that window\n * — before any rendering starts — so a header set there is on the answer. A\n * component runs after it, during streaming, where the status line and headers\n * are already on the wire; setting one there is refused rather than dropped.\n */\ninterface Draft {\n headers: Headers;\n sealed: boolean;\n /**\n * What this request wrote to the jar, over what it arrived with: a value,\n * or null for a deletion. Read back by `cookies()` for the rest of the\n * request, so a render that follows the write - the sections an action\n * revalidates travel back with its answer, rendered in the same request -\n * sees what the browser is about to hold. Next has the same rule, which\n * is why `set` then `revalidate` is what every port writes; without it\n * the sidebar re-rendered with the cookie the request arrived with, and\n * showed the old choice until a reload.\n */\n cookies: Map<string, string | null>;\n}\n\nconst DRAFT = Symbol.for(\"@rsc-kit/core.response-draft\");\n\nlet draftReady: Promise<void> | null = null;\n\ninterface DraftScope {\n getStore(): Draft | undefined;\n run<T>(store: Draft, fn: () => T): T;\n}\n\nfunction draft(): DraftScope | null {\n return (globals[DRAFT] as DraftScope | undefined) ?? null;\n}\n\n/** The open draft, or an explanation of why there is not one. */\nfunction writable(what: string): Draft {\n const open = draft()?.getStore();\n\n if (!open) {\n throw new Error(\n `${what} needs a response that has not been sent. Middleware and server actions have one; ` +\n \"a script outside a request does not.\",\n );\n }\n\n if (open.sealed) {\n throw new Error(\n `${what} was called after the response had been sent. Headers go out before the render ` +\n \"starts — that is what makes the first paint fast — so set them in middleware, which \" +\n \"runs before it.\",\n );\n }\n\n return open;\n}\n\n/**\n * Headers to put on the answer.\n *\n * Mutate it as you would any Headers. `append` is the one to reach for when a\n * header may legitimately appear twice; `set` replaces.\n */\n/**\n * The draft's headers, refusing writes once the response has gone.\n *\n * A proxy rather than the Headers itself: returning the live object means code\n * that captured it before the response was built can go on mutating a thing\n * nobody will read. Nothing in this package does that — the host copies the\n * headers onto the response the instant it seals — but \"safe because of the\n * order two other functions happen to run in\" is not a property, and an app\n * holding the object across an await would find writes silently doing nothing.\n */\nfunction sealable(draft: Draft): Headers {\n const guard =\n (method: \"set\" | \"append\" | \"delete\") =>\n (...args: [string, string]) => {\n writable(\"responseHeaders()\");\n\n return (draft.headers[method] as (...a: string[]) => void)(...args);\n };\n\n const proxy: Headers = new Proxy(draft.headers, {\n get(target, property, receiver) {\n if (\n property === \"set\" ||\n property === \"append\" ||\n property === \"delete\"\n ) {\n return guard(property);\n }\n\n // A maplike forEach passes the object it was called on as the third\n // callback argument, and binding to the target makes that the raw\n // Headers — a live, unguarded reference handed out by the very method\n // meant to be read-only. Substituted for the proxy so there is no way\n // through.\n if (property === \"forEach\") {\n return (\n fn: (value: string, key: string, parent: Headers) => void,\n thisArg?: unknown,\n ) =>\n target.forEach((value, key) => fn.call(thisArg, value, key, proxy));\n }\n\n const value = Reflect.get(target, property, receiver);\n\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n });\n\n return proxy;\n}\n\n/**\n * Cookies a backend set while answering a host call - a login - put on the\n * page's response, as if the page had set them. Only while the response is\n * open: an action or middleware. A call made after the headers went out - a\n * read inside a Suspense boundary - has nothing to put them on, which is why\n * reads do not set cookies; said once, not dropped silently.\n */\nexport function passSetCookies(setCookies: string[]): void {\n if (setCookies.length === 0) return;\n\n const open = draft()?.getStore();\n\n if (!open) return;\n\n if (open.sealed) {\n if (!warnedLateCookie) {\n warnedLateCookie = true;\n console.warn(\n \"[rsc-kit] the backend set a cookie while answering a call made after the response was sent, \" +\n \"so it cannot reach the browser. Set cookies from an action or middleware.\",\n );\n }\n\n return;\n }\n\n for (const cookie of setCookies) {\n open.headers.append(\"Set-Cookie\", cookie);\n\n // The jar a later cookies() read sees: this request's own write.\n const pair = cookie.split(\";\", 1)[0] ?? \"\";\n const at = pair.indexOf(\"=\");\n\n if (at > 0) open.cookies.set(pair.slice(0, at).trim(), pair.slice(at + 1).trim());\n }\n}\n\nlet warnedLateCookie = false;\n\nexport function responseHeaders(): Headers {\n return sealable(writable(\"responseHeaders()\"));\n}\n\n/**\n * Run a request with a response that can still be changed, and take what was\n * put on it.\n *\n * `seal()` is called by the host the moment it builds the Response, so\n * anything set afterwards is refused instead of silently going nowhere.\n */\nexport async function withResponseDraft<T>(\n run: (draft: { taken: () => Headers; seal: () => void }) => Promise<T>,\n): Promise<T> {\n if (!globals[DRAFT]) {\n draftReady ??= resolveScope().then((resolved) => {\n globals[DRAFT] ??= resolved as unknown as DraftScope;\n });\n\n await draftReady;\n }\n\n const open: Draft = { headers: new Headers(), sealed: false, cookies: new Map() };\n\n return await draft()!.run(open, () =>\n run({\n taken: () => open.headers,\n seal: () => {\n open.sealed = true;\n },\n }),\n );\n}\n\n/**\n * A cookie name, as RFC 6265 defines one: a token, so no separators at all.\n *\n * Checked rather than escaped because there is no escaping — a name is not a\n * quoted string. An app that derives one from user input (`pref_${key}`) would\n * otherwise let that input close the pair and open another: a name of\n * `session=attacker; Path=/; HttpOnly; x` serializes to a header whose *first*\n * pair is a session cookie the caller chose, and the browser reads the first.\n */\nconst COOKIE_NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\n/** No separator may appear in an attribute either, for the same reason. */\nconst COOKIE_ATTRIBUTE = /[;,\\r\\n]/;\n\n/** `name=value; Path=/; HttpOnly` — the header a browser expects. */\nexport function serializeCookie(cookie: {\n name: string;\n value: string;\n options: CookieOptions;\n}): string {\n if (!COOKIE_NAME.test(cookie.name)) {\n throw new Error(\n `Not a usable cookie name: ${JSON.stringify(cookie.name)}. ` +\n \"A name is a token — letters, digits and !#$%&'*+-.^_`|~ — with no spaces, \" +\n \"semicolons or equals signs. Nothing escapes them, so one cannot be encoded around.\",\n );\n }\n\n if (cookie.options.sameSite !== undefined) {\n const value = String(cookie.options.sameSite).toLowerCase();\n\n if (value !== \"strict\" && value !== \"lax\" && value !== \"none\") {\n throw new Error(\n `Not a SameSite value: ${JSON.stringify(cookie.options.sameSite)}. ` +\n \"It is written into the header as given, so anything else becomes further attributes.\",\n );\n }\n }\n\n for (const [attribute, value] of [\n [\"path\", cookie.options.path],\n [\"domain\", cookie.options.domain],\n ] as const) {\n if (typeof value === \"string\" && COOKIE_ATTRIBUTE.test(value)) {\n throw new Error(\n `The cookie ${attribute} ${JSON.stringify(value)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n }\n\n // Typed as a Date, but a cast reaches this and the result lands in the\n // header verbatim. Checked apart from the others because a date has commas\n // in it by definition - \"Sun, 20 Sep 2026 14:49:56 GMT\" - and the general\n // check refused every Expires ever written.\n const expires = cookie.options.expires?.toUTCString();\n\n if (typeof expires === \"string\" && /[;\\r\\n]/.test(expires)) {\n throw new Error(\n `The cookie expires ${JSON.stringify(expires)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n\n const parts = [`${cookie.name}=${encodeURIComponent(cookie.value)}`];\n const o = cookie.options;\n\n if (o.maxAge !== undefined) parts.push(`Max-Age=${Math.floor(o.maxAge)}`);\n if (o.expires) parts.push(`Expires=${o.expires.toUTCString()}`);\n // Defaulted, because a cookie without one is scoped to the path that set it\n // — a session written by POST /_rsc/action would not be sent for any page.\n parts.push(`Path=${o.path ?? \"/\"}`);\n if (o.domain) parts.push(`Domain=${o.domain}`);\n if (o.sameSite)\n parts.push(`SameSite=${o.sameSite[0].toUpperCase()}${o.sameSite.slice(1)}`);\n if (o.secure) parts.push(\"Secure\");\n if (o.httpOnly) parts.push(\"HttpOnly\");\n if (o.partitioned) parts.push(\"Partitioned\");\n\n return parts.join(\"; \");\n}\n\nexport async function cookies(): Promise<Cookies> {\n // Named before the await, because `headers()` never settles during a build —\n // nothing after this line runs there, and the reason would be recorded as\n // headers() for a call nobody wrote.\n const store = slot();\n\n if (!store.request) recordRead(store, \"cookies()\");\n\n const parsed = parseCookies((await headers()).get(\"cookie\") ?? \"\");\n\n // What arrived, then what this request wrote over it. Read at each call\n // rather than once: a write between two reads is the case that matters.\n const jar = (): Record<string, string> => {\n const written = draft()?.getStore()?.cookies;\n\n if (!written?.size) return parsed;\n\n const merged = { ...parsed };\n\n for (const [name, value] of written) {\n if (value === null) delete merged[name];\n else merged[name] = value;\n }\n\n return merged;\n };\n\n const write = (\n name: string,\n value: string,\n options: CookieOptions = {},\n ): void => {\n const open = writable(\"cookies().set()\");\n\n // Appended, never set: several cookies on one response are several\n // Set-Cookie headers, and replacing would leave only the last.\n open.headers.append(\"Set-Cookie\", serializeCookie({ name, value, options }));\n\n // A cookie told to expire is one the browser will not send back.\n const gone =\n options.maxAge !== undefined ? options.maxAge <= 0 : options.expires !== undefined && options.expires.getTime() <= Date.now();\n\n open.cookies.set(name, gone ? null : value);\n };\n\n return {\n get: (name) => {\n const current = jar();\n\n // Own keys only: `in` found \"constructor\" in any jar.\n return Object.hasOwn(current, name) ? { name, value: current[name] } : undefined;\n },\n has: (name) => Object.hasOwn(jar(), name),\n getAll: () => Object.entries(jar()).map(([name, value]) => ({ name, value })),\n set: (nameOrCookie: string | (RequestCookie & CookieOptions), value?: string, options?: CookieOptions) => {\n if (typeof nameOrCookie === \"string\") return write(nameOrCookie, value ?? \"\", options);\n\n const { name, value: v, ...rest } = nameOrCookie;\n\n return write(name, v, rest);\n },\n // Expired rather than removed: a browser drops a cookie when it is told\n // one has already passed, and there is no other way to say it.\n delete: (name, options = {}) => write(name, \"\", { ...options, maxAge: 0 }),\n };\n}\n\n/**\n * The whole request, for a host-specific need the accessors do not cover.\n *\n * Null on a host that forwards only the parts — the worker behind Laravel has\n * a socket, not a request. Use headers() and cookies(), which work everywhere.\n */\nexport async function request(): Promise<Request | null> {\n const store = slot();\n\n return store.request ? store.original : never(\"request()\");\n}\n\n/**\n * Mark everything below as belonging to the request, not to the build.\n *\n * export default async function Orders() {\n * await connection()\n *\n * const rows = await db.query('select * from orders')\n *\n * return <ul>{rows.map(...)}</ul>\n * }\n *\n * At build time this never resolves, so nothing after it runs: the query is not\n * made, the boundary above becomes a hole, and the rest of the page still\n * freezes. At request time it resolves immediately and the component runs\n * normally.\n *\n * **Once is enough.** It is a barrier, not a wrapper — everything after it in\n * this component belongs to the request, however many calls that is. Repeating\n * it before each query does nothing.\n *\n * It needs a boundary above it. With a <Suspense> or a loading.tsx there is a\n * fallback to store and the page becomes a shell; with neither, nothing can\n * paint and the build refuses the route rather than storing a blank.\n *\n * Reach for it when the build should not run something — a database the build\n * machine cannot see, or a value that must differ per visitor. A query the\n * build CAN run, whose answer is the same for everyone, wants none of this: it\n * should be frozen.\n *\n * The same name and behaviour as Next's `connection()`.\n */\nexport async function connection(): Promise<void> {\n const store = slot();\n\n // No request means a build. Suspend rather than continue, the same way\n // headers() and cookies() do.\n if (!store.request) return never(\"connection()\");\n}\n\n/**\n * The query of the request being rendered - `?q=shoes`, or \"\" - and null when\n * there is no request: a build, whose render may be stored. For the server's\n * HTML render, which hands it to useSearchParams. Not a read of the request:\n * the render it serves is per request already.\n */\nexport function requestSearch(): string | null {\n const store = scope()?.getStore();\n\n if (!store?.request || !store.url) return null;\n\n try {\n return new URL(store.url, \"http://rsc.invalid\").search;\n } catch {\n return null;\n }\n}\n\n/**\n * Whether the request being rendered is a crawler's, which is answered with\n * the finished document - see crawler.ts. False when there is no request.\n */\nexport function requestFromCrawler(): boolean {\n const store = scope()?.getStore();\n\n return Boolean(store?.request && isCrawler(store.headers.get(\"user-agent\")));\n}\n\n/** The url this request was made to, whichever way the host supplied it. */\nexport async function url(): Promise<string | null> {\n const store = slot();\n\n return store.request ? store.url : never(\"url()\");\n}\n\nfunction parseCookies(header: string): Record<string, string> {\n const out: Record<string, string> = {};\n\n for (const part of header.split(\";\")) {\n const eq = part.indexOf(\"=\");\n\n if (eq === -1) continue;\n\n const name = part.slice(0, eq).trim();\n\n if (!name) continue;\n\n // Decoded because that is how they were written. A malformed escape is\n // left as it arrived rather than throwing the render away.\n const raw = part.slice(eq + 1).trim();\n\n try {\n out[name] = decodeURIComponent(raw);\n } catch {\n out[name] = raw;\n }\n }\n\n return out;\n}\n\n/**\n * Run one request with its headers readable.\n *\n * `null` is the build: a scope with nothing in it, so a page that reads is\n * caught rather than silently frozen holding whatever the machine that built\n * it happened to send.\n */\nexport async function withRequest<T>(\n from: RequestLike,\n run: () => Promise<T>,\n): Promise<T> {\n if (!globals[SCOPE]) {\n ready ??= resolveScope().then((resolved) => {\n globals[SCOPE] ??= resolved as unknown as Scope;\n });\n\n await ready;\n }\n\n const isRequest = from instanceof Request;\n const store: Slot = {\n request: from !== null,\n url: from ? (isRequest ? from.url : from.url) : null,\n headers: from\n ? isRequest\n ? from.headers\n : new Headers(from.headers)\n : new Headers(),\n original: isRequest ? from : null,\n read: false,\n readBy: [],\n readWhere: [],\n fallbacks: [],\n awaiters: new Map(),\n inHelper: null,\n readVia: new Map(),\n after: [],\n };\n\n return await scope()!.run(store, run);\n}\n\n/**\n * Run a render with a different url, the request otherwise unchanged.\n *\n * An action's response renders what it revalidated for the page it was called\n * from. The request is the action's POST, whose url is the endpoint's; the\n * page's query string lives in the page's url. A slot on /agent/test?c=25\n * re-rendered after a message was sent read the POST's empty query - through\n * searchParams() and through the page's own searchParams prop, which is built\n * on it - and came back as a new chat. Headers and cookies stay the request's:\n * it is the same visitor, asking about a different url.\n */\nexport async function withUrl<T>(href: string, run: () => Promise<T>): Promise<T> {\n const store = slot();\n\n if (!store.request) return await run();\n\n return await scope()!.run({ ...store, url: href }, run);\n}\n\n/**\n * A promise that never settles, so the caller suspends.\n *\n * What a read does during a build. React treats it exactly as it treats a host\n * call that never answers: the component suspends, its Suspense fallback goes\n * into the shell, and the probe's budget decides the rest.\n */\n/**\n * The build's probe hands a route a Request that records what is read out of\n * it, and a read of `url` marks the route as depending on the caller — the\n * Next way to read a query is `new URL(request.url).searchParams`, which the\n * probe cannot otherwise see. The engine itself reads the url to resolve the\n * awaited `searchParams`, and that read is accounted for by `searchParams`,\n * not by `url`; this is the door it goes through. A probe answers the real\n * Request to this key; anything else answers nothing, and the request is its\n * own.\n */\nexport const UNPROBED = Symbol.for(\"rsc-kit.unprobed\");\n\n/** The request's url, read by the engine rather than the route. */\nexport function urlOf(request: Request): string {\n return ((request as unknown as Record<symbol, Request | undefined>)[UNPROBED] ?? request).url;\n}\n\n/**\n * Record a read without suspending on it.\n *\n * For a reader that CAN answer during a build but whose answer would be wrong\n * to store — an api route's query string, which exists and is empty, and which\n * the build has no business freezing an answer to. `never()` is for a reader\n * with nothing to return; this is for one that has something and should still\n * be noticed.\n *\n * A no-op outside a render scope, so a handler called at request time pays a\n * property read and nothing else.\n */\nexport function noteRequestRead(by: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n recordRead(store, by);\n}\n\nfunction never(by: string): Promise<never> {\n const store = slot();\n\n store.read = true;\n recordRead(store, by);\n\n return new Promise(() => {});\n}\n\n/**\n * Whether anything read the request during the scope that is open.\n *\n * For the prerenderer, which opens one with no request and asks afterwards.\n */\nexport function requestWasRead(): boolean {\n return scope()?.getStore()?.read ?? false;\n}\n\n/**\n * What reached for the request during the scope that is open.\n *\n * For the build, which asks afterwards so it can say why a page is rendered per\n * visitor rather than only that it is.\n */\nexport function requestReadBy(): string[] {\n return scope()?.getStore()?.readBy ?? [];\n}\n\n/** A read React caught at a boundary during SSR: `useSearchParams() in Query`. */\nexport function noteFallback(text: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n store.fallbacks ??= [];\n\n if (!store.fallbacks.includes(text)) store.fallbacks.push(text);\n}\n\n/**\n * Run something once the answer is on its way, without making it wait.\n *\n * Logging, an audit row, an email, a cache warm: work the visitor should not\n * pay for, and that must still finish. Next's `after()`, and needed for the\n * same reason on every host: on a long-lived process a detached promise\n * happens to run to completion, but a Worker tears the isolate down when the\n * response ends unless the work is registered with the platform's\n * `waitUntil` - so a fire-and-forget promise there dies silently, some of\n * the time. The host hands these to `waitUntil` where one exists and runs\n * them detached where a process will keep them.\n *\n * From a component, a middleware, a server action or an api route. A\n * rejection is reported and never reaches the response, which has already\n * gone. Outside a request - a build - the work runs at once.\n */\nexport function after(work: () => unknown): void {\n const store = scope()?.getStore();\n\n if (!store || !store.request) {\n void Promise.resolve().then(work).catch(reportAfter);\n\n return;\n }\n\n store.after.push(work);\n}\n\nfunction reportAfter(error: unknown): void {\n console.error(\"[rsc-kit] after() work failed:\", error);\n}\n\n/**\n * @internal For the host: the work `after()` collected for this request, as\n * one promise that never rejects. Taken once; a second call has nothing.\n */\nexport function takeAfterWork(): Promise<void> | null {\n const store = scope()?.getStore();\n\n if (!store || store.after.length === 0) return null;\n\n const work = store.after.splice(0);\n\n return Promise.allSettled(\n work.map((run) => Promise.resolve().then(run)),\n ).then((results) => {\n for (const result of results) {\n if (result.status === \"rejected\") reportAfter(result.reason);\n }\n });\n}\n\n/** The reads caught at a boundary during this render, with their components. */\nexport function requestFallbacks(): string[] {\n return scope()?.getStore()?.fallbacks ?? [];\n}\n\n/**\n * A component called a cache()-wrapped helper. Recorded on every call, hit\n * or miss, so a read the helper makes can name everyone who waited for it.\n */\nexport function noteAwaiter(helper: unknown): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n const { name } = caller(\"cache\");\n\n if (!name) return;\n\n store.awaiters ??= new Map();\n\n const list = store.awaiters.get(helper) ?? [];\n\n if (!list.includes(name)) list.push(name);\n\n store.awaiters.set(helper, list);\n}\n\n/** Run a cache()-wrapped helper's body, so a read inside it is filed under the helper. */\nexport function withHelper<T>(helper: unknown, run: () => T): T {\n const store = scope()?.getStore();\n\n if (!store) return run();\n\n const before = store.inHelper;\n\n store.inHelper = helper;\n\n try {\n return run();\n } finally {\n store.inHelper = before;\n }\n}\n\n/**\n * The same reads, each with the component that made it: `cookies() in\n * RootLayout`. A read inside a cached helper with more than one awaiter\n * names them all - `connection() awaited by AuthLinks, AuthDialogSlot` -\n * because the stack saw only the first, and the first is rarely the one\n * that blocks.\n */\nexport function requestReadWhere(): string[] {\n const store = scope()?.getStore();\n\n if (!store?.readWhere?.length) return store?.readBy ?? [];\n\n return store.readWhere.map((entry) => {\n const helper = store.readVia?.get(entry);\n const awaiters = helper ? store.awaiters?.get(helper) : undefined;\n\n if (!awaiters || awaiters.length < 2) return entry;\n\n const names =\n awaiters.length === 2\n ? awaiters.join(\" and \")\n : awaiters.slice(0, -1).join(\", \") + \" and \" + awaiters.at(-1);\n\n return `${entry.split(\" in \")[0]} awaited by ${names}`;\n });\n}\n\n/**\n * The query string, as a page receives it.\n *\n * Derived from the request rather than passed down the render, so no host has\n * to forward it separately — and so it suspends during a build for the same\n * reason every other read does. A frozen page cannot know the query it will be\n * asked for.\n */\nexport async function searchParams(): Promise<URLSearchParams> {\n // Named before the await, so the build reports the call someone wrote rather\n // than url(), which this happens to be built on.\n const store = slot();\n\n if (!store.request && !store.readBy.includes(\"searchParams()\")) {\n store.readBy.push(\"searchParams()\");\n }\n\n const from = await url();\n\n return from ? new URL(from).searchParams : new URLSearchParams();\n}\n\n/**\n * The props the page is being rendered with, for whatever renders inside it.\n *\n * A section is rendered by its page with whatever the page passed, which is\n * usually nothing, and alone - on a refresh - with the page's own props. Its\n * refreshOn is a function of the page's params either way, so the engine notes\n * them here and the section reads them back, whichever way it was rendered.\n */\nexport function notePageProps(props: Record<string, unknown>): void {\n const store = scope()?.getStore();\n\n if (store) store.pageProps = props;\n}\n\n/** The page's props as noted by the engine; empty outside a page render. */\nexport function currentPageProps(): Record<string, unknown> {\n return scope()?.getStore()?.pageProps ?? {};\n}\n"]}
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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","sourcesContent":["// Reading the request from inside a render.\n//\n// import { headers, cookies } from '@rsc-kit/core/request'\n//\n// export default async function middleware() {\n// const locale = cookies().get('locale')?.value ?? negotiate(headers().get('accept-language'))\n// if (!locale) redirect('/en')\n// }\n//\n// Server components have no arguments beyond their props, and middleware has\n// none at all, so without this an app on a JavaScript host cannot see a header\n// — no locale negotiation, no subdomain, no cookie. The Laravel host escaped\n// that through rpc(), because PHP has the request; this is the same thing for\n// everyone else.\n//\n// Read-only on purpose. Setting a cookie means writing a response header, and\n// by the time a component renders the shell may already have been flushed — an\n// API that appears to set one and silently does not is worse than not having\n// it. Set them in the host, which owns the response.\n//\n// Asynchronous on purpose too, and not for ergonomics. A build has no request,\n// so a read there suspends and never settles — which is the same thing the\n// prerender probe does to a host call. Anything still waiting when the probe's\n// budget expires becomes a fallback in the frozen shell, so a read inside a\n// Suspense boundary leaves the shell frozen and makes only that boundary\n// dynamic. Reading synchronously could only mark the whole route dynamic,\n// because there would be nothing to suspend on.\n//\n// Scoped to the request, on the same store cache() uses. Two requests in\n// flight cannot see each other's headers.\n\nimport { isCrawler } from \"./crawler.js\";\nimport { resolveScope } from \"./revalidate.js\";\n\nexport type { ServedRequest } from \"./served.js\";\n\n/** What a host can supply: a real Request, or the parts of one. */\nexport type RequestLike =\n Request | { url: string; headers: Record<string, string> } | null;\n\ninterface Slot {\n /** False during a build: there is nothing to answer with. */\n request: boolean;\n url: string | null;\n /**\n * Held as Headers rather than as a Request.\n *\n * `new Request(url, { headers })` drops Cookie: a spec-compliant Headers\n * built with the \"request\" guard refuses the forbidden header names, and\n * Cookie is one of them. `new Headers()` has no guard and keeps it. Bun\n * happens to allow both, which is why rebuilding a Request looked fine until\n * it ran anywhere stricter — and what it loses is every cookie, silently.\n */\n headers: Headers;\n original: Request | null;\n /**\n * Whether anything asked. Only for the build's report — the classification\n * comes from the suspension, not from this.\n */\n read: boolean;\n /**\n * What read it, in the order they did.\n *\n * Only the name of the accessor — `cookies()`, `headers()` — which is enough\n * for the build to say why a page could not be frozen. Without it the answer\n * is \"something in this page reached for the request\", and finding which is\n * the part that takes an afternoon.\n */\n readBy: string[];\n /**\n * The same reads with the component that made each one - `cookies() in\n * RootLayout` - taken from the stack at the moment of the read, which is\n * still the component's own call: an accessor runs synchronously up to\n * the point it suspends. Only the build reads this. \"Reads the request\" is\n * a category; this is the line to open.\n */\n readWhere: string[];\n /**\n * Reads the server could not answer and React caught at a boundary - the\n * fallback is what got stored - with the component that made each:\n * `useSearchParams() in Query`. Noted by the SSR entry, read by the build,\n * which attaches them to the route so a page stored as its own loading\n * screen says why.\n */\n fallbacks: string[];\n /**\n * For a read made inside a cache()-wrapped helper: the components that\n * awaited that helper, first caller included. The helper runs once, so\n * the stack at the read names only whoever got there first; every later\n * awaiter is a cache hit that never reaches the accessor. The one above\n * every boundary is usually one of the later ones.\n */\n awaiters: Map<unknown, string[]>;\n /** The cache()-wrapped helper whose body is running, while it runs. */\n inHelper: unknown;\n /** readWhere entry -> the helper it was read inside. */\n readVia: Map<string, unknown>;\n /** Work to run once the answer is on its way - see after(). */\n after: (() => unknown)[];\n /** The props the page was rendered with - its params and searchParams - for a region rendered inside it to read. */\n pageProps?: Record<string, unknown>;\n}\n\nconst SCOPE = Symbol.for(\"@rsc-kit/core.request-scope\");\n\n/**\n * The accessors themselves and the plumbing under them: frames to walk past\n * on the way to the component that called.\n */\nconst NOT_A_CALLER = new Set([\n \"never\",\n // A thenable's own method: the read is named by what it was for.\n \"then\",\n \"cache\",\n \"noteAwaiter\",\n \"withHelper\",\n \"noteRequestRead\",\n \"recordRead\",\n \"caller\",\n \"slot\",\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n \"parseParams\",\n \"parseSearchParams\",\n \"parseBody\",\n \"get\",\n \"set\",\n \"has\",\n]);\n\n/** The accessors a component calls by name. One calling another is plumbing, not a second read. */\nconst ACCESSORS = new Set([\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n]);\n\n/**\n * The nearest named function above the accessor on the stack, and whether\n * another accessor sits between: `cookies()` reads through `headers()`, and\n * that inner read is not a second thing the component did.\n *\n * Read from a thrown-away Error: the one thing a build cannot otherwise learn\n * is which component reached for the request, and the stack knows. Function\n * names survive a server bundle, which is not minified, so this is\n * `RootLayout` and not a line number in a chunk. Internal names are walked\n * past; an anonymous frame is skipped rather than reported as `<anonymous>`.\n */\nfunction caller(own: string): { name: string | null; nested: boolean } {\n const stack = new Error().stack ?? \"\";\n let accessors = 0;\n let helper: string | null = null;\n\n for (const line of stack.split(\"\\n\")) {\n const match = /^\\s*at (?:async )?([^\\s(]+)/.exec(line);\n\n if (!match) continue;\n\n const name = match[1]!.split(\".\").pop()!;\n\n // A frame with no function name prints its location instead - `js:6054:8`\n // - which is not a name to report.\n if (!/^[\\w$]+$/.test(name)) continue;\n\n if (ACCESSORS.has(name)) accessors++;\n if (\n NOT_A_CALLER.has(name) ||\n name === \"<anonymous>\" ||\n name === \"Object\" ||\n name === \"Promise\"\n )\n continue;\n\n const nested = accessors > (ACCESSORS.has(own) ? 1 : 0);\n\n // A function that is not a component - getCurrentUser, wrapped in\n // cache() - is the shared helper the read lives in. Named, because with\n // cache() the read runs once, on whichever component called first, and\n // every other caller of the helper is invisible to the stack. The helper\n // is what they have in common.\n if (/^[a-z_$]/.test(name) && !/^use[A-Z]/.test(name)) {\n helper ??= name;\n\n continue;\n }\n\n return {\n name: helper && helper !== name ? `${helper} (from ${name})` : name,\n nested,\n };\n }\n\n return { name: helper, nested: accessors > (ACCESSORS.has(own) ? 1 : 0) };\n}\n\nfunction recordRead(store: Slot, by: string): void {\n if (!store.readBy.includes(by)) store.readBy.push(by);\n\n // Older stores, written by a bundle built before this field existed.\n store.readWhere ??= [];\n\n const { name, nested } = caller(by.replace(/\\(.*$/, \"\"));\n\n if (nested) return;\n\n const entry = name ? `${by} in ${name}` : by;\n\n if (!store.readWhere.includes(entry)) store.readWhere.push(entry);\n if (store.inHelper) (store.readVia ??= new Map()).set(entry, store.inHelper);\n}\n\nconst globals = globalThis as Record<symbol | string, unknown>;\n\nlet ready: Promise<void> | null = null;\n\ninterface Scope {\n getStore(): Slot | undefined;\n run<T>(store: Slot, fn: () => T): T;\n}\n\nfunction scope(): Scope | null {\n return (globals[SCOPE] as Scope | undefined) ?? null;\n}\n\nfunction slot(): Slot {\n const store = scope()?.getStore();\n\n if (!store) {\n throw new Error(\n \"No request in scope. headers() and cookies() are for a render — middleware, a layout, \" +\n \"a page — and there is nothing to read outside one.\",\n );\n }\n\n store.read = true;\n\n return store;\n}\n\n/**\n * The request's headers.\n *\n * Empty during a build, where there is no request: the page is marked as\n * needing one instead, and rendered on demand rather than frozen.\n */\nexport async function headers(): Promise<Headers> {\n const store = slot();\n\n return store.request ? store.headers : never(\"headers()\");\n}\n\n/** How a cookie should be written. The names browsers use. */\nexport interface CookieOptions {\n path?: string;\n domain?: string;\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n partitioned?: boolean;\n}\n\n/** One cookie as the request carried it: the shape Next's `cookies().get()` returns. */\nexport interface RequestCookie {\n name: string;\n value: string;\n}\n\n/**\n * The cookie jar, in the shape Next's `cookies()` has.\n *\n * `get()` returns `{ name, value }` rather than the string, because the guide\n * says \"the same names from `@rsc-kit/core/request`\" and a name that is the\n * same with a different return shape is the worst of both: ported code\n * reading `?.value` off a string got `undefined`, silently. `getAll()` is a\n * list for the same reason, and because a list composes where a record does\n * not.\n */\nexport interface Cookies {\n get(name: string): RequestCookie | undefined;\n has(name: string): boolean;\n getAll(): RequestCookie[];\n /**\n * Write one on the response.\n *\n * Only from a server action, which has a response of its own that has not\n * been sent. A render has already flushed its headers by the time a\n * component runs — that is what makes the first paint fast — so this throws\n * there rather than appearing to work.\n *\n * Either call shape Next takes: `set(name, value, options)` or\n * `set({ name, value, ...options })`.\n */\n set(name: string, value: string, options?: CookieOptions): void;\n set(cookie: RequestCookie & CookieOptions): void;\n /** Write one that expires immediately. Same rule about where. */\n delete(name: string, options?: CookieOptions): void;\n}\n\n/** Kept for the name it had when it could only read. */\nexport type ReadonlyCookies = Cookies;\n\n/**\n * The response being built, while it can still be changed.\n *\n * Open from the moment a request is picked up until the host constructs its\n * Response, and sealed the instant it does. Middleware runs inside that window\n * — before any rendering starts — so a header set there is on the answer. A\n * component runs after it, during streaming, where the status line and headers\n * are already on the wire; setting one there is refused rather than dropped.\n */\ninterface Draft {\n headers: Headers;\n sealed: boolean;\n /**\n * What this request wrote to the jar, over what it arrived with: a value,\n * or null for a deletion. Read back by `cookies()` for the rest of the\n * request, so a render that follows the write - the sections an action\n * revalidates travel back with its answer, rendered in the same request -\n * sees what the browser is about to hold. Next has the same rule, which\n * is why `set` then `revalidate` is what every port writes; without it\n * the sidebar re-rendered with the cookie the request arrived with, and\n * showed the old choice until a reload.\n */\n cookies: Map<string, string | null>;\n}\n\nconst DRAFT = Symbol.for(\"@rsc-kit/core.response-draft\");\n\nlet draftReady: Promise<void> | null = null;\n\ninterface DraftScope {\n getStore(): Draft | undefined;\n run<T>(store: Draft, fn: () => T): T;\n}\n\nfunction draft(): DraftScope | null {\n return (globals[DRAFT] as DraftScope | undefined) ?? null;\n}\n\n/** The open draft, or an explanation of why there is not one. */\nfunction writable(what: string): Draft {\n const open = draft()?.getStore();\n\n if (!open) {\n throw new Error(\n `${what} needs a response that has not been sent. Middleware and server actions have one; ` +\n \"a script outside a request does not.\",\n );\n }\n\n if (open.sealed) {\n throw new Error(\n `${what} was called after the response had been sent. Headers go out before the render ` +\n \"starts — that is what makes the first paint fast — so set them in middleware, which \" +\n \"runs before it.\",\n );\n }\n\n return open;\n}\n\n/**\n * Headers to put on the answer.\n *\n * Mutate it as you would any Headers. `append` is the one to reach for when a\n * header may legitimately appear twice; `set` replaces.\n */\n/**\n * The draft's headers, refusing writes once the response has gone.\n *\n * A proxy rather than the Headers itself: returning the live object means code\n * that captured it before the response was built can go on mutating a thing\n * nobody will read. Nothing in this package does that — the host copies the\n * headers onto the response the instant it seals — but \"safe because of the\n * order two other functions happen to run in\" is not a property, and an app\n * holding the object across an await would find writes silently doing nothing.\n */\nfunction sealable(draft: Draft): Headers {\n const guard =\n (method: \"set\" | \"append\" | \"delete\") =>\n (...args: [string, string]) => {\n writable(\"responseHeaders()\");\n\n return (draft.headers[method] as (...a: string[]) => void)(...args);\n };\n\n const proxy: Headers = new Proxy(draft.headers, {\n get(target, property, receiver) {\n if (\n property === \"set\" ||\n property === \"append\" ||\n property === \"delete\"\n ) {\n return guard(property);\n }\n\n // A maplike forEach passes the object it was called on as the third\n // callback argument, and binding to the target makes that the raw\n // Headers — a live, unguarded reference handed out by the very method\n // meant to be read-only. Substituted for the proxy so there is no way\n // through.\n if (property === \"forEach\") {\n return (\n fn: (value: string, key: string, parent: Headers) => void,\n thisArg?: unknown,\n ) =>\n target.forEach((value, key) => fn.call(thisArg, value, key, proxy));\n }\n\n const value = Reflect.get(target, property, receiver);\n\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n });\n\n return proxy;\n}\n\n/**\n * Cookies a backend set while answering a host call - a login - put on the\n * page's response, as if the page had set them. Only while the response is\n * open: an action or middleware. A call made after the headers went out - a\n * read inside a Suspense boundary - has nothing to put them on, which is why\n * reads do not set cookies; said once, not dropped silently.\n */\nexport function passSetCookies(setCookies: string[]): void {\n if (setCookies.length === 0) return;\n\n const open = draft()?.getStore();\n\n if (!open) return;\n\n if (open.sealed) {\n if (!warnedLateCookie) {\n warnedLateCookie = true;\n console.warn(\n \"[rsc-kit] the backend set a cookie while answering a call made after the response was sent, \" +\n \"so it cannot reach the browser. Set cookies from an action or middleware.\",\n );\n }\n\n return;\n }\n\n for (const cookie of setCookies) {\n open.headers.append(\"Set-Cookie\", cookie);\n\n // The jar a later cookies() read sees: this request's own write.\n const pair = cookie.split(\";\", 1)[0] ?? \"\";\n const at = pair.indexOf(\"=\");\n\n if (at > 0) open.cookies.set(pair.slice(0, at).trim(), pair.slice(at + 1).trim());\n }\n}\n\nlet warnedLateCookie = false;\n\nexport function responseHeaders(): Headers {\n return sealable(writable(\"responseHeaders()\"));\n}\n\n/**\n * Run a request with a response that can still be changed, and take what was\n * put on it.\n *\n * `seal()` is called by the host the moment it builds the Response, so\n * anything set afterwards is refused instead of silently going nowhere.\n */\nexport async function withResponseDraft<T>(\n run: (draft: { taken: () => Headers; seal: () => void }) => Promise<T>,\n): Promise<T> {\n if (!globals[DRAFT]) {\n draftReady ??= resolveScope().then((resolved) => {\n globals[DRAFT] ??= resolved as unknown as DraftScope;\n });\n\n await draftReady;\n }\n\n const open: Draft = { headers: new Headers(), sealed: false, cookies: new Map() };\n\n return await draft()!.run(open, () =>\n run({\n taken: () => open.headers,\n seal: () => {\n open.sealed = true;\n },\n }),\n );\n}\n\n/**\n * A cookie name, as RFC 6265 defines one: a token, so no separators at all.\n *\n * Checked rather than escaped because there is no escaping — a name is not a\n * quoted string. An app that derives one from user input (`pref_${key}`) would\n * otherwise let that input close the pair and open another: a name of\n * `session=attacker; Path=/; HttpOnly; x` serializes to a header whose *first*\n * pair is a session cookie the caller chose, and the browser reads the first.\n */\nconst COOKIE_NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\n/** No separator may appear in an attribute either, for the same reason. */\nconst COOKIE_ATTRIBUTE = /[;,\\r\\n]/;\n\n/** `name=value; Path=/; HttpOnly` — the header a browser expects. */\nexport function serializeCookie(cookie: {\n name: string;\n value: string;\n options: CookieOptions;\n}): string {\n if (!COOKIE_NAME.test(cookie.name)) {\n throw new Error(\n `Not a usable cookie name: ${JSON.stringify(cookie.name)}. ` +\n \"A name is a token — letters, digits and !#$%&'*+-.^_`|~ — with no spaces, \" +\n \"semicolons or equals signs. Nothing escapes them, so one cannot be encoded around.\",\n );\n }\n\n if (cookie.options.sameSite !== undefined) {\n const value = String(cookie.options.sameSite).toLowerCase();\n\n if (value !== \"strict\" && value !== \"lax\" && value !== \"none\") {\n throw new Error(\n `Not a SameSite value: ${JSON.stringify(cookie.options.sameSite)}. ` +\n \"It is written into the header as given, so anything else becomes further attributes.\",\n );\n }\n }\n\n for (const [attribute, value] of [\n [\"path\", cookie.options.path],\n [\"domain\", cookie.options.domain],\n ] as const) {\n if (typeof value === \"string\" && COOKIE_ATTRIBUTE.test(value)) {\n throw new Error(\n `The cookie ${attribute} ${JSON.stringify(value)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n }\n\n // Typed as a Date, but a cast reaches this and the result lands in the\n // header verbatim. Checked apart from the others because a date has commas\n // in it by definition - \"Sun, 20 Sep 2026 14:49:56 GMT\" - and the general\n // check refused every Expires ever written.\n const expires = cookie.options.expires?.toUTCString();\n\n if (typeof expires === \"string\" && /[;\\r\\n]/.test(expires)) {\n throw new Error(\n `The cookie expires ${JSON.stringify(expires)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n\n const parts = [`${cookie.name}=${encodeURIComponent(cookie.value)}`];\n const o = cookie.options;\n\n if (o.maxAge !== undefined) parts.push(`Max-Age=${Math.floor(o.maxAge)}`);\n if (o.expires) parts.push(`Expires=${o.expires.toUTCString()}`);\n // Defaulted, because a cookie without one is scoped to the path that set it\n // — a session written by POST /_rsc/action would not be sent for any page.\n parts.push(`Path=${o.path ?? \"/\"}`);\n if (o.domain) parts.push(`Domain=${o.domain}`);\n if (o.sameSite)\n parts.push(`SameSite=${o.sameSite[0].toUpperCase()}${o.sameSite.slice(1)}`);\n if (o.secure) parts.push(\"Secure\");\n if (o.httpOnly) parts.push(\"HttpOnly\");\n if (o.partitioned) parts.push(\"Partitioned\");\n\n return parts.join(\"; \");\n}\n\nexport async function cookies(): Promise<Cookies> {\n // Named before the await, because `headers()` never settles during a build —\n // nothing after this line runs there, and the reason would be recorded as\n // headers() for a call nobody wrote.\n const store = slot();\n\n if (!store.request) recordRead(store, \"cookies()\");\n\n const parsed = parseCookies((await headers()).get(\"cookie\") ?? \"\");\n\n // What arrived, then what this request wrote over it. Read at each call\n // rather than once: a write between two reads is the case that matters.\n const jar = (): Record<string, string> => {\n const written = draft()?.getStore()?.cookies;\n\n if (!written?.size) return parsed;\n\n const merged = { ...parsed };\n\n for (const [name, value] of written) {\n if (value === null) delete merged[name];\n else merged[name] = value;\n }\n\n return merged;\n };\n\n const write = (\n name: string,\n value: string,\n options: CookieOptions = {},\n ): void => {\n const open = writable(\"cookies().set()\");\n\n // Appended, never set: several cookies on one response are several\n // Set-Cookie headers, and replacing would leave only the last.\n open.headers.append(\"Set-Cookie\", serializeCookie({ name, value, options }));\n\n // A cookie told to expire is one the browser will not send back.\n const gone =\n options.maxAge !== undefined ? options.maxAge <= 0 : options.expires !== undefined && options.expires.getTime() <= Date.now();\n\n open.cookies.set(name, gone ? null : value);\n };\n\n return {\n get: (name) => {\n const current = jar();\n\n // Own keys only: `in` found \"constructor\" in any jar.\n return Object.hasOwn(current, name) ? { name, value: current[name] } : undefined;\n },\n has: (name) => Object.hasOwn(jar(), name),\n getAll: () => Object.entries(jar()).map(([name, value]) => ({ name, value })),\n set: (nameOrCookie: string | (RequestCookie & CookieOptions), value?: string, options?: CookieOptions) => {\n if (typeof nameOrCookie === \"string\") return write(nameOrCookie, value ?? \"\", options);\n\n const { name, value: v, ...rest } = nameOrCookie;\n\n return write(name, v, rest);\n },\n // Expired rather than removed: a browser drops a cookie when it is told\n // one has already passed, and there is no other way to say it.\n delete: (name, options = {}) => write(name, \"\", { ...options, maxAge: 0 }),\n };\n}\n\n/**\n * The whole request, for a host-specific need the accessors do not cover.\n *\n * Null on a host that forwards only the parts — the worker behind Laravel has\n * a socket, not a request. Use headers() and cookies(), which work everywhere.\n */\nexport async function request(): Promise<Request | null> {\n const store = slot();\n\n return store.request ? store.original : never(\"request()\");\n}\n\n/**\n * Mark everything below as belonging to the request, not to the build.\n *\n * export default async function Orders() {\n * await connection()\n *\n * const rows = await db.query('select * from orders')\n *\n * return <ul>{rows.map(...)}</ul>\n * }\n *\n * At build time this never resolves, so nothing after it runs: the query is not\n * made, the boundary above becomes a hole, and the rest of the page still\n * freezes. At request time it resolves immediately and the component runs\n * normally.\n *\n * **Once is enough.** It is a barrier, not a wrapper — everything after it in\n * this component belongs to the request, however many calls that is. Repeating\n * it before each query does nothing.\n *\n * It needs a boundary above it. With a <Suspense> or a loading.tsx there is a\n * fallback to store and the page becomes a shell; with neither, nothing can\n * paint and the build refuses the route rather than storing a blank.\n *\n * Reach for it when the build should not run something — a database the build\n * machine cannot see, or a value that must differ per visitor. A query the\n * build CAN run, whose answer is the same for everyone, wants none of this: it\n * should be frozen.\n *\n * The same name and behaviour as Next's `connection()`.\n */\nexport async function connection(): Promise<void> {\n const store = slot();\n\n // No request means a build. Suspend rather than continue, the same way\n // headers() and cookies() do.\n if (!store.request) return never(\"connection()\");\n}\n\n/**\n * The query of the request being rendered - `?q=shoes`, or \"\" - and null when\n * there is no request: a build, whose render may be stored. For the server's\n * HTML render, which hands it to useSearchParams. Not a read of the request:\n * the render it serves is per request already.\n */\nexport function requestSearch(): string | null {\n const store = scope()?.getStore();\n\n if (!store?.request || !store.url) return null;\n\n try {\n return new URL(store.url, \"http://rsc.invalid\").search;\n } catch {\n return null;\n }\n}\n\n/**\n * Whether the request being rendered is a crawler's, which is answered with\n * the finished document - see crawler.ts. False when there is no request.\n */\nexport function requestFromCrawler(): boolean {\n const store = scope()?.getStore();\n\n return Boolean(store?.request && isCrawler(store.headers.get(\"user-agent\")));\n}\n\n/** The url this request was made to, whichever way the host supplied it. */\nexport async function url(): Promise<string | null> {\n const store = slot();\n\n return store.request ? store.url : never(\"url()\");\n}\n\nfunction parseCookies(header: string): Record<string, string> {\n const out: Record<string, string> = {};\n\n for (const part of header.split(\";\")) {\n const eq = part.indexOf(\"=\");\n\n if (eq === -1) continue;\n\n const name = part.slice(0, eq).trim();\n\n if (!name) continue;\n\n // Decoded because that is how they were written. A malformed escape is\n // left as it arrived rather than throwing the render away.\n const raw = part.slice(eq + 1).trim();\n\n try {\n out[name] = decodeURIComponent(raw);\n } catch {\n out[name] = raw;\n }\n }\n\n return out;\n}\n\n/**\n * Run one request with its headers readable.\n *\n * `null` is the build: a scope with nothing in it, so a page that reads is\n * caught rather than silently frozen holding whatever the machine that built\n * it happened to send.\n */\nexport async function withRequest<T>(\n from: RequestLike,\n run: () => Promise<T>,\n): Promise<T> {\n if (!globals[SCOPE]) {\n ready ??= resolveScope().then((resolved) => {\n globals[SCOPE] ??= resolved as unknown as Scope;\n });\n\n await ready;\n }\n\n const isRequest = from instanceof Request;\n const store: Slot = {\n request: from !== null,\n url: from ? (isRequest ? from.url : from.url) : null,\n headers: from\n ? isRequest\n ? from.headers\n : new Headers(from.headers)\n : new Headers(),\n original: isRequest ? from : null,\n read: false,\n readBy: [],\n readWhere: [],\n fallbacks: [],\n awaiters: new Map(),\n inHelper: null,\n readVia: new Map(),\n after: [],\n };\n\n return await scope()!.run(store, run);\n}\n\n/**\n * Run a render with a different url, the request otherwise unchanged.\n *\n * An action's response renders what it revalidated for the page it was called\n * from. The request is the action's POST, whose url is the endpoint's; the\n * page's query string lives in the page's url. A slot on /agent/test?c=25\n * re-rendered after a message was sent read the POST's empty query - through\n * searchParams() and through the page's own searchParams prop, which is built\n * on it - and came back as a new chat. Headers and cookies stay the request's:\n * it is the same visitor, asking about a different url.\n */\nexport async function withUrl<T>(href: string, run: () => Promise<T>): Promise<T> {\n const store = slot();\n\n if (!store.request) return await run();\n\n return await scope()!.run({ ...store, url: href }, run);\n}\n\n/**\n * A promise that never settles, so the caller suspends.\n *\n * What a read does during a build. React treats it exactly as it treats a host\n * call that never answers: the component suspends, its Suspense fallback goes\n * into the shell, and the probe's budget decides the rest.\n */\n/**\n * The build's probe hands a route a Request that records what is read out of\n * it, and a read of `url` marks the route as depending on the caller — the\n * Next way to read a query is `new URL(request.url).searchParams`, which the\n * probe cannot otherwise see. The engine itself reads the url to resolve the\n * awaited `searchParams`, and that read is accounted for by `searchParams`,\n * not by `url`; this is the door it goes through. A probe answers the real\n * Request to this key; anything else answers nothing, and the request is its\n * own.\n */\nexport const UNPROBED = Symbol.for(\"rsc-kit.unprobed\");\n\n/** The request's url, read by the engine rather than the route. */\nexport function urlOf(request: Request): string {\n return ((request as unknown as Record<symbol, Request | undefined>)[UNPROBED] ?? request).url;\n}\n\n/**\n * Record a read without suspending on it.\n *\n * For a reader that CAN answer during a build but whose answer would be wrong\n * to store — an api route's query string, which exists and is empty, and which\n * the build has no business freezing an answer to. `never()` is for a reader\n * with nothing to return; this is for one that has something and should still\n * be noticed.\n *\n * A no-op outside a render scope, so a handler called at request time pays a\n * property read and nothing else.\n */\nexport function noteRequestRead(by: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n recordRead(store, by);\n}\n\nfunction never(by: string): Promise<never> {\n const store = slot();\n\n store.read = true;\n recordRead(store, by);\n\n return new Promise(() => {});\n}\n\n/**\n * Whether anything read the request during the scope that is open.\n *\n * For the prerenderer, which opens one with no request and asks afterwards.\n */\nexport function requestWasRead(): boolean {\n return scope()?.getStore()?.read ?? false;\n}\n\n/**\n * What reached for the request during the scope that is open.\n *\n * For the build, which asks afterwards so it can say why a page is rendered per\n * visitor rather than only that it is.\n */\nexport function requestReadBy(): string[] {\n return scope()?.getStore()?.readBy ?? [];\n}\n\n/** A read React caught at a boundary during SSR: `useSearchParams() in Query`. */\nexport function noteFallback(text: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n store.fallbacks ??= [];\n\n if (!store.fallbacks.includes(text)) store.fallbacks.push(text);\n}\n\n/**\n * Run something once the answer is on its way, without making it wait.\n *\n * Logging, an audit row, an email, a cache warm: work the visitor should not\n * pay for, and that must still finish. Next's `after()`, and needed for the\n * same reason on every host: on a long-lived process a detached promise\n * happens to run to completion, but a Worker tears the isolate down when the\n * response ends unless the work is registered with the platform's\n * `waitUntil` - so a fire-and-forget promise there dies silently, some of\n * the time. The host hands these to `waitUntil` where one exists and runs\n * them detached where a process will keep them.\n *\n * From a component, a middleware, a server action or an api route. A\n * rejection is reported and never reaches the response, which has already\n * gone. Outside a request - a build - the work runs at once.\n */\nexport function after(work: () => unknown): void {\n const store = scope()?.getStore();\n\n if (!store || !store.request) {\n void Promise.resolve().then(work).catch(reportAfter);\n\n return;\n }\n\n store.after.push(work);\n}\n\nfunction reportAfter(error: unknown): void {\n console.error(\"[rsc-kit] after() work failed:\", error);\n}\n\n/**\n * @internal For the host: the work `after()` collected for this request, as\n * one promise that never rejects. Taken once; a second call has nothing.\n */\nexport function takeAfterWork(): Promise<void> | null {\n const store = scope()?.getStore();\n\n if (!store || store.after.length === 0) return null;\n\n const work = store.after.splice(0);\n\n return Promise.allSettled(\n work.map((run) => Promise.resolve().then(run)),\n ).then((results) => {\n for (const result of results) {\n if (result.status === \"rejected\") reportAfter(result.reason);\n }\n });\n}\n\n/** The reads caught at a boundary during this render, with their components. */\nexport function requestFallbacks(): string[] {\n return scope()?.getStore()?.fallbacks ?? [];\n}\n\n/**\n * A component called a cache()-wrapped helper. Recorded on every call, hit\n * or miss, so a read the helper makes can name everyone who waited for it.\n */\nexport function noteAwaiter(helper: unknown): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n const { name } = caller(\"cache\");\n\n if (!name) return;\n\n store.awaiters ??= new Map();\n\n const list = store.awaiters.get(helper) ?? [];\n\n if (!list.includes(name)) list.push(name);\n\n store.awaiters.set(helper, list);\n}\n\n/** Run a cache()-wrapped helper's body, so a read inside it is filed under the helper. */\nexport function withHelper<T>(helper: unknown, run: () => T): T {\n const store = scope()?.getStore();\n\n if (!store) return run();\n\n const before = store.inHelper;\n\n store.inHelper = helper;\n\n try {\n return run();\n } finally {\n store.inHelper = before;\n }\n}\n\n/**\n * The same reads, each with the component that made it: `cookies() in\n * RootLayout`. A read inside a cached helper with more than one awaiter\n * names them all - `connection() awaited by AuthLinks, AuthDialogSlot` -\n * because the stack saw only the first, and the first is rarely the one\n * that blocks.\n */\nexport function requestReadWhere(): string[] {\n const store = scope()?.getStore();\n\n if (!store?.readWhere?.length) return store?.readBy ?? [];\n\n return store.readWhere.map((entry) => {\n const helper = store.readVia?.get(entry);\n const awaiters = helper ? store.awaiters?.get(helper) : undefined;\n\n if (!awaiters || awaiters.length < 2) return entry;\n\n const names =\n awaiters.length === 2\n ? awaiters.join(\" and \")\n : awaiters.slice(0, -1).join(\", \") + \" and \" + awaiters.at(-1);\n\n return `${entry.split(\" in \")[0]} awaited by ${names}`;\n });\n}\n\n/**\n * The query string, as a page receives it.\n *\n * Derived from the request rather than passed down the render, so no host has\n * to forward it separately — and so it suspends during a build for the same\n * reason every other read does. A frozen page cannot know the query it will be\n * asked for.\n */\nexport async function searchParams(): Promise<URLSearchParams> {\n // Named before the await, so the build reports the call someone wrote rather\n // than url(), which this happens to be built on.\n const store = slot();\n\n if (!store.request && !store.readBy.includes(\"searchParams()\")) {\n store.readBy.push(\"searchParams()\");\n }\n\n const from = await url();\n\n return from ? new URL(from).searchParams : new URLSearchParams();\n}\n\n/**\n * The props the page is being rendered with, for whatever renders inside it.\n *\n * A section is rendered by its page with whatever the page passed, which is\n * usually nothing, and alone - on a refresh - with the page's own props. Its\n * refreshOn is a function of the page's params either way, so the engine notes\n * them here and the section reads them back, whichever way it was rendered.\n */\nexport function notePageProps(props: Record<string, unknown>): void {\n const store = scope()?.getStore();\n\n if (store) store.pageProps = props;\n}\n\n/** The page's props as noted by the engine; empty outside a page render. */\nexport function currentPageProps(): Record<string, unknown> {\n return scope()?.getStore()?.pageProps ?? {};\n}\n"]}
package/dist/routes.d.ts CHANGED
@@ -43,7 +43,19 @@ type OffRoute = `${string}://${string}` | `mailto:${string}` | `tel:${string}` |
43
43
  * `Route` is the same type under the name Next uses, so a port keeps the
44
44
  * word it already has.
45
45
  */
46
- export type Route = Unregistered extends true ? string : Filled<RoutePattern> | `${Filled<RoutePattern>}?${string}` | `${Filled<RoutePattern>}#${string}` | Filled<ApiPattern> | `${Filled<ApiPattern>}?${string}` | OffRoute;
46
+ export type Route = Unregistered extends true ? string : Filled<RoutePattern> | `${Filled<RoutePattern>}?${string}` | `${Filled<RoutePattern>}#${string}` | Filled<ApiPattern> | `${Filled<ApiPattern>}?${string}` | BackendUrl | OffRoute;
47
+ /** Augmented by the generated `rsc-routes.d.ts`, like `Register`. */
48
+ export interface RegisterBackend {
49
+ }
50
+ /** The prefixes `backendPaths` named: `'/gitlab'`. */
51
+ type BackendPrefix = RegisterBackend extends {
52
+ paths: infer P extends string;
53
+ } ? P : never;
54
+ /**
55
+ * A prefix and everything under it, at a segment boundary: `/gitlab`,
56
+ * `/gitlab/connect?next=/`, never `/gitlabs`. `never` when nothing was named.
57
+ */
58
+ type BackendUrl = BackendPrefix | `${BackendPrefix}/${string}` | `${BackendPrefix}?${string}` | `${BackendPrefix}#${string}`;
47
59
  /** Augmented by the generated `rsc-routes.d.ts`, like `Register`. */
48
60
  export interface RegisterApi {
49
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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","sourcesContent":["// Typed routes: the urls this app can actually answer, as a type.\n//\n// Laravel needs route() because the url lives in PHP and can move\n// independently of the name it is called by. Here the url *is* the file path,\n// so a name would be indirection that buys nothing. What is worth having is\n// the other half — a link to a page that does not exist should fail at build\n// time rather than in the browser.\n//\n// There is no route() builder to go with this, deliberately. A template\n// literal is checked the same way — `/posts/${slug}` compiles and\n// `/postz/${slug}` does not — so a builder would only wrap what the language\n// already does. Encoding a value that is not url-safe is `encodeURIComponent`\n// in the template, the same as anywhere else.\n//\n// The build already walks app/ and knows every route's segments, so it writes\n// one line into the app's source dir:\n//\n// declare module '@rsc-kit/core/routes' {\n// interface Register { routes: '/' | '/posts/[slug]' }\n// }\n//\n// Everything below is derived from that union. An app that never runs the\n// generator — a generic host, a Laravel app that has not rebuilt — registers\n// nothing, `RoutePattern` stays `string`, and every url-taking API is exactly\n// as permissive as it was before. That fallback is the reason this can ship\n// without a flag.\n\n/**\n * Augmented by the generated `rsc-routes.d.ts`. Empty here on purpose.\n *\n * Declaration merging rather than a generic parameter, because the routes are\n * a property of the project, not of each call site — threading them through\n * every component that renders a Link is not a thing anyone would do twice.\n */\nexport interface Register {}\n\n/** The route patterns this app declared: `'/posts/[slug]'`. */\nexport type RoutePattern = Register extends { routes: infer R extends string }\n ? R\n : string;\n\n/** Whether anything was registered. `string` means the generator never ran. */\ntype Unregistered = string extends RoutePattern ? true : false;\n\n/**\n * A pattern with its dynamic segments opened up: `/posts/[slug]` accepts\n * `/posts/anything`.\n *\n * Catch-all and single params both become `${string}`, which for a catch-all\n * also swallows the slashes — `/docs/[...path]` accepts `/docs/a/b/c`.\n */\ntype Filled<P extends string> = P extends `${infer A}[...${string}]${infer B}`\n ? `${A}${string}${Filled<B>}`\n : P extends `${infer A}[${string}]${infer B}`\n ? `${A}${string}${Filled<B>}`\n : P;\n\n/**\n * Not a route, but a legitimate href: another site, a mail client, a phone\n * number, an anchor on this page, a bare query string.\n */\ntype OffRoute =\n | `${string}://${string}`\n | `mailto:${string}`\n | `tel:${string}`\n | `#${string}`\n | `?${string}`;\n\n/**\n * A url this app can answer, or one that deliberately leaves it.\n *\n * Cast when the destination is computed rather than written:\n * `href={path as Route}`.\n */\n/**\n * A url this app answers - a page or a route.ts - or one that deliberately\n * leaves it. One type, as Next's `Route` is one type: what `<Link href>`,\n * `visit()` and `redirect()` take. A route.ts is a full navigation rather\n * than a payload fetch, and never prefetched - the client knows which urls\n * are routes and treats a link to one as the anchor it is - so the type\n * does not have to keep them apart to keep a hover from running one.\n *\n * `Route` is the same type under the name Next uses, so a port keeps the\n * word it already has.\n */\nexport type Route = Unregistered extends true\n ? string\n : | Filled<RoutePattern>\n | `${Filled<RoutePattern>}?${string}`\n | `${Filled<RoutePattern>}#${string}`\n | Filled<ApiPattern>\n | `${Filled<ApiPattern>}?${string}`\n | OffRoute;\n\n// ── Api routes ───────────────────────────────────────────────────────────────\n//\n// Their own union rather than part of Route, because they are not pages and a\n// link to one is almost always a mistake — an <a href=\"/api/orders\"> navigates\n// the browser away to a json document. Keeping them apart means `Link` refuses\n// an api url and `apiUrl()` refuses a page, which is the pair of mistakes worth\n// catching.\n\n/** Augmented by the generated `rsc-routes.d.ts`, like `Register`. */\nexport interface RegisterApi {}\n\n// ── Regions a page can re-render on its own ──────────────────────────────────\n//\n// Every `section('name', …)` the build found, and every `@slot` directory.\n// `revalidate('orders')` is checked against them, so a name that matches no\n// section - a typo, or a section renamed since - stops compiling instead of\n// being refused by the renderer at runtime.\n\n/** Augmented by the generated `rsc-routes.d.ts`, like `Register`. */\nexport interface RegisterRegions {}\n\n/** The region names the build found: section names and slot names. */\nexport type RegionName = RegisterRegions extends {\n regions: infer R extends string;\n}\n ? R\n : string;\n\ntype NoRegions = string extends RegionName ? true : false;\n\n/**\n * What `revalidate()` takes: the page, the whole document, or a region by\n * name. `string` until the build has written the types.\n */\nexport type RevalidateTarget = NoRegions extends true\n ? string\n : \"page\" | \"all\" | RegionName;\n\n/** The api route patterns this app declared: `'/api/orders/[id]'`. */\nexport type ApiPattern = RegisterApi extends { apis: infer R extends string }\n ? R\n : string;\n\ntype NoApis = string extends ApiPattern ? true : false;\n\n/**\n * A url an api route in this app answers.\n *\n * `/api/orders/[id]` accepts `/api/orders/42`, and a query string is allowed\n * because that is how a GET is parameterised.\n */\nexport type ApiRoute = NoApis extends true\n ? string\n : Filled<ApiPattern> | `${Filled<ApiPattern>}?${string}`;\n\n/**\n * An api url, checked against the routes the build found.\n *\n * await fetch(apiUrl(`/api/orders/${id}`))\n *\n * A function rather than a bare type so it can be used inline at a call site\n * that is typed `string` — `fetch` takes any string, so nothing would check the\n * argument without somewhere to put the type. It returns what it was given.\n *\n * Wrong path, and it stops compiling. Renamed the directory, and every call\n * site says so rather than one of them 404ing in production.\n */\nexport function apiUrl(href: ApiRoute): string {\n return href;\n}\n\n// ── What an events route sends ───────────────────────────────────────────────\n//\n// A route.ts whose GET is `events(...)` says, as a type, what its generator\n// yields. The generated file records that per api pattern:\n//\n// interface RegisterApi {\n// events: { '/api/orders/[id]/events': EventsExportOf<typeof import('../src/app/api/orders/[id]/events/route')> }\n// }\n//\n// and `useEvents` reads a url's messages from it, so the hook and the route\n// cannot disagree about a message's shape.\n\n/** What a route module's GET yields, when it is `events(...)`; `unknown` for any other stream. */\nexport type EventsExportOf<M> = M extends {\n GET: { readonly \"~events\"?: infer S };\n}\n ? NonNullable<S> extends { yields: infer Y }\n ? Y\n : unknown\n : unknown;\n\ntype EventsMap = RegisterApi extends { events: infer M } ? M : {};\n\ntype Split<S extends string> = S extends `${infer A}/${infer B}`\n ? [A, ...Split<B>]\n : [S];\n\n/**\n * Whether a url's segments fit a pattern's, one segment at a time. Unlike\n * `Filled`, a `[id]` takes exactly one segment, so `/api/orders/42/events`\n * is `/api/orders/[id]/events` and not also `/api/orders/[id]`.\n */\ntype Fits<H extends string[], P extends string[]> = P extends [\n infer P0 extends string,\n ...infer PR extends string[],\n]\n ? P0 extends `[...${string}]`\n ? H extends [string, ...string[]]\n ? true\n : false\n : H extends [infer H0 extends string, ...infer HR extends string[]]\n ? P0 extends `[${string}]`\n ? Fits<HR, PR>\n : H0 extends P0\n ? Fits<HR, PR>\n : false\n : false\n : H extends []\n ? true\n : false;\n\n/** The api pattern a written url belongs to: `/api/orders/42/events` is `/api/orders/[id]/events`. */\ntype ApiPatternOf<H extends string> = ApiPattern extends infer P\n ? P extends string\n ? Fits<Split<StripQuery<H>>, Split<P>> extends true\n ? P\n : never\n : never\n : never;\n\n/**\n * Everything the stream at `H` yields, named events included. `unknown` when\n * `H` is not one api route the build found - a url computed at runtime, or\n * another site's - since there is nothing to read it from.\n */\nexport type EventsAt<H extends string> = NoApis extends true\n ? unknown\n : IsUnion<H> extends true\n ? unknown\n : [ApiPatternOf<H>] extends [never]\n ? unknown\n : ApiPatternOf<H> extends keyof EventsMap\n ? EventsMap[ApiPatternOf<H>]\n : unknown;\n\n/** A url `useEvents` may open: an api route this app answers, or another site's stream. */\nexport type EventsUrl = ApiRoute | `${string}://${string}`;\n\n// ── Search params, typed per route ───────────────────────────────────────────\n//\n// A page that exports a `searchParams` schema has said what its query string\n// means. The generated file records that schema per pattern:\n//\n// interface Register {\n// search: { '/search': SearchExportOf<typeof import('../src/app/search/page')> }\n// }\n//\n// and from there a link to `/search` is checked against the same schema the\n// page parses with — a `page` that must be a number is a number on the link,\n// a `q` the page requires is required to write the link, and a key the page\n// never reads does not compile. One schema, both ends. A route that exports\n// none takes anything; an href that is not a single route (computed, cast, or\n// off-site) takes anything too, because there is nothing to check it against.\n\n/** What a page module contributes: its `searchParams` export, or nothing. For the generated file. */\nexport type SearchExportOf<M> = M extends { searchParams: infer S }\n ? S\n : undefined;\n\ntype SearchMap = Register extends { search: infer M } ? M : {};\n\ntype StripQuery<H extends string> = H extends `${infer P}?${string}`\n ? P\n : H extends `${infer P}#${string}`\n ? P\n : H;\n\n/** The pattern a written href belongs to: `/posts/hello` is `/posts/[slug]`. */\ntype PatternOf<H extends string> = RoutePattern extends infer P\n ? P extends string\n ? StripQuery<H> extends Filled<P>\n ? P\n : never\n : never\n : never;\n\ntype IsUnion<T, U = T> = T extends unknown\n ? [U] extends [T]\n ? false\n : true\n : never;\n\ntype SchemaFor<P> = P extends keyof SearchMap ? SearchMap[P] : undefined;\n\ntype InputOf<S> = S extends { \"~standard\": { types?: { input: infer I } } }\n ? I\n : never;\ntype OutputOf<S> = S extends { \"~standard\": { types?: { output: infer O } } }\n ? O\n : never;\n\ntype OptionalKeys<T> = {\n [K in keyof T]-?: {} extends Pick<T, K> ? K : never;\n}[keyof T];\ntype RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\n/**\n * What a link may write for a schema: the keys the schema's input requires\n * are required, the rest optional, and every value is the schema's OUTPUT\n * type. Output rather than input because `z.coerce.number()` takes `unknown`\n * in - that is what coercion means - and a link typed by it would accept\n * `page: 'two'`. The output is the number the page will actually see.\n */\ntype LinkInputOf<S> = Simplify<\n { [K in RequiredKeys<InputOf<S>> & keyof OutputOf<S>]: OutputOf<S>[K] } & {\n [K in OptionalKeys<InputOf<S>> & keyof OutputOf<S>]?: OutputOf<S>[K];\n }\n>;\n\ntype Scalar = string | number | boolean | null | undefined;\n\n/** What a link may carry when nothing declares otherwise. */\nexport type LooseSearch = Record<string, Scalar | readonly (string | number)[]>;\n\n/**\n * The search params a link to `H` may carry.\n *\n * The page's schema input when `H` is one declared route with a schema;\n * otherwise anything. \"One route\" matters: `path as Route` is every route at\n * once, and a link that could go anywhere cannot be held to one page's schema.\n */\nexport type SearchFor<H extends string> = Unregistered extends true\n ? LooseSearch\n : IsUnion<H> extends true\n ? LooseSearch\n : [PatternOf<H>] extends [never]\n ? LooseSearch\n : SchemaFor<PatternOf<H>> extends undefined\n ? LooseSearch\n : LinkInputOf<SchemaFor<PatternOf<H>>>;\n\n/**\n * The `search` prop, required exactly when the page's schema has a required\n * key. A page that needs `q` is not reachable without one, so the link that\n * omits it is the bug — caught here rather than on the page's error boundary.\n */\nexport type SearchProp<H extends string> =\n {} extends SearchFor<H>\n ? { search?: SearchFor<H> }\n : { search: SearchFor<H> };\n\n/** A query string from an object: scalars stringified, arrays repeated, null and undefined dropped. */\nexport function searchString(search: object): string {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(search)) {\n if (value === null || value === undefined) continue;\n\n if (Array.isArray(value)) {\n for (const item of value) params.append(key, String(item));\n } else {\n params.set(key, String(value));\n }\n }\n\n return params.toString();\n}\n\n/** `path` with `search` appended, keeping any query and hash already on it. */\nexport function withSearch(path: string, search: object | undefined): string {\n if (!search) return path;\n\n const hashAt = path.indexOf(\"#\");\n const hash = hashAt === -1 ? \"\" : path.slice(hashAt);\n const before = hashAt === -1 ? path : path.slice(0, hashAt);\n const queryAt = before.indexOf(\"?\");\n const base = queryAt === -1 ? before : before.slice(0, queryAt);\n const existing = queryAt === -1 ? \"\" : before.slice(queryAt + 1);\n const added = searchString(search);\n const query = [existing, added].filter(Boolean).join(\"&\");\n\n return query ? `${base}?${query}${hash}` : `${base}${hash}`;\n}\n\n/**\n * A typed url with its search params, for the places that take a string.\n *\n * visit(href('/search', { q: 'shoes', page: 2 }))\n *\n * `Link` has the same check on its own `search` prop. This is for `visit`,\n * `prefetch`, `redirect` and anything else that wants the finished string.\n */\nexport function href<H extends Route>(\n path: H,\n ...rest: {} extends SearchFor<H>\n ? [search?: SearchFor<H>]\n : [search: SearchFor<H>]\n): Route {\n return withSearch(path, rest[0] as object | undefined) as Route;\n}\n"]}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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","sourcesContent":["// Typed routes: the urls this app can actually answer, as a type.\n//\n// Laravel needs route() because the url lives in PHP and can move\n// independently of the name it is called by. Here the url *is* the file path,\n// so a name would be indirection that buys nothing. What is worth having is\n// the other half — a link to a page that does not exist should fail at build\n// time rather than in the browser.\n//\n// There is no route() builder to go with this, deliberately. A template\n// literal is checked the same way — `/posts/${slug}` compiles and\n// `/postz/${slug}` does not — so a builder would only wrap what the language\n// already does. Encoding a value that is not url-safe is `encodeURIComponent`\n// in the template, the same as anywhere else.\n//\n// The build already walks app/ and knows every route's segments, so it writes\n// one line into the app's source dir:\n//\n// declare module '@rsc-kit/core/routes' {\n// interface Register { routes: '/' | '/posts/[slug]' }\n// }\n//\n// Everything below is derived from that union. An app that never runs the\n// generator — a generic host, a Laravel app that has not rebuilt — registers\n// nothing, `RoutePattern` stays `string`, and every url-taking API is exactly\n// as permissive as it was before. That fallback is the reason this can ship\n// without a flag.\n\n/**\n * Augmented by the generated `rsc-routes.d.ts`. Empty here on purpose.\n *\n * Declaration merging rather than a generic parameter, because the routes are\n * a property of the project, not of each call site — threading them through\n * every component that renders a Link is not a thing anyone would do twice.\n */\nexport interface Register {}\n\n/** The route patterns this app declared: `'/posts/[slug]'`. */\nexport type RoutePattern = Register extends { routes: infer R extends string }\n ? R\n : string;\n\n/** Whether anything was registered. `string` means the generator never ran. */\ntype Unregistered = string extends RoutePattern ? true : false;\n\n/**\n * A pattern with its dynamic segments opened up: `/posts/[slug]` accepts\n * `/posts/anything`.\n *\n * Catch-all and single params both become `${string}`, which for a catch-all\n * also swallows the slashes — `/docs/[...path]` accepts `/docs/a/b/c`.\n */\ntype Filled<P extends string> = P extends `${infer A}[...${string}]${infer B}`\n ? `${A}${string}${Filled<B>}`\n : P extends `${infer A}[${string}]${infer B}`\n ? `${A}${string}${Filled<B>}`\n : P;\n\n/**\n * Not a route, but a legitimate href: another site, a mail client, a phone\n * number, an anchor on this page, a bare query string.\n */\ntype OffRoute =\n | `${string}://${string}`\n | `mailto:${string}`\n | `tel:${string}`\n | `#${string}`\n | `?${string}`;\n\n/**\n * A url this app can answer, or one that deliberately leaves it.\n *\n * Cast when the destination is computed rather than written:\n * `href={path as Route}`.\n */\n/**\n * A url this app answers - a page or a route.ts - or one that deliberately\n * leaves it. One type, as Next's `Route` is one type: what `<Link href>`,\n * `visit()` and `redirect()` take. A route.ts is a full navigation rather\n * than a payload fetch, and never prefetched - the client knows which urls\n * are routes and treats a link to one as the anchor it is - so the type\n * does not have to keep them apart to keep a hover from running one.\n *\n * `Route` is the same type under the name Next uses, so a port keeps the\n * word it already has.\n */\nexport type Route = Unregistered extends true\n ? string\n : | Filled<RoutePattern>\n | `${Filled<RoutePattern>}?${string}`\n | `${Filled<RoutePattern>}#${string}`\n | Filled<ApiPattern>\n | `${Filled<ApiPattern>}?${string}`\n | BackendUrl\n | OffRoute;\n\n// ── The backend's urls ───────────────────────────────────────────────────────\n//\n// `rscKit({ backendPaths: ['/gitlab'] })` names the prefixes the backend owns.\n// They are not in the route tree, so a link or a redirect to `/gitlab/connect`\n// needed a cast to compile, for a url the app itself had declared. They are a\n// place to go and, like a route.ts, a full page load.\n\n/** Augmented by the generated `rsc-routes.d.ts`, like `Register`. */\nexport interface RegisterBackend {}\n\n/** The prefixes `backendPaths` named: `'/gitlab'`. */\ntype BackendPrefix = RegisterBackend extends { paths: infer P extends string }\n ? P\n : never;\n\n/**\n * A prefix and everything under it, at a segment boundary: `/gitlab`,\n * `/gitlab/connect?next=/`, never `/gitlabs`. `never` when nothing was named.\n */\ntype BackendUrl =\n | BackendPrefix\n | `${BackendPrefix}/${string}`\n | `${BackendPrefix}?${string}`\n | `${BackendPrefix}#${string}`;\n\n// ── Api routes ───────────────────────────────────────────────────────────────\n//\n// Their own union rather than part of Route, because they are not pages and a\n// link to one is almost always a mistake — an <a href=\"/api/orders\"> navigates\n// the browser away to a json document. Keeping them apart means `Link` refuses\n// an api url and `apiUrl()` refuses a page, which is the pair of mistakes worth\n// catching.\n\n/** Augmented by the generated `rsc-routes.d.ts`, like `Register`. */\nexport interface RegisterApi {}\n\n// ── Regions a page can re-render on its own ──────────────────────────────────\n//\n// Every `section('name', …)` the build found, and every `@slot` directory.\n// `revalidate('orders')` is checked against them, so a name that matches no\n// section - a typo, or a section renamed since - stops compiling instead of\n// being refused by the renderer at runtime.\n\n/** Augmented by the generated `rsc-routes.d.ts`, like `Register`. */\nexport interface RegisterRegions {}\n\n/** The region names the build found: section names and slot names. */\nexport type RegionName = RegisterRegions extends {\n regions: infer R extends string;\n}\n ? R\n : string;\n\ntype NoRegions = string extends RegionName ? true : false;\n\n/**\n * What `revalidate()` takes: the page, the whole document, or a region by\n * name. `string` until the build has written the types.\n */\nexport type RevalidateTarget = NoRegions extends true\n ? string\n : \"page\" | \"all\" | RegionName;\n\n/** The api route patterns this app declared: `'/api/orders/[id]'`. */\nexport type ApiPattern = RegisterApi extends { apis: infer R extends string }\n ? R\n : string;\n\ntype NoApis = string extends ApiPattern ? true : false;\n\n/**\n * A url an api route in this app answers.\n *\n * `/api/orders/[id]` accepts `/api/orders/42`, and a query string is allowed\n * because that is how a GET is parameterised.\n */\nexport type ApiRoute = NoApis extends true\n ? string\n : Filled<ApiPattern> | `${Filled<ApiPattern>}?${string}`;\n\n/**\n * An api url, checked against the routes the build found.\n *\n * await fetch(apiUrl(`/api/orders/${id}`))\n *\n * A function rather than a bare type so it can be used inline at a call site\n * that is typed `string` — `fetch` takes any string, so nothing would check the\n * argument without somewhere to put the type. It returns what it was given.\n *\n * Wrong path, and it stops compiling. Renamed the directory, and every call\n * site says so rather than one of them 404ing in production.\n */\nexport function apiUrl(href: ApiRoute): string {\n return href;\n}\n\n// ── What an events route sends ───────────────────────────────────────────────\n//\n// A route.ts whose GET is `events(...)` says, as a type, what its generator\n// yields. The generated file records that per api pattern:\n//\n// interface RegisterApi {\n// events: { '/api/orders/[id]/events': EventsExportOf<typeof import('../src/app/api/orders/[id]/events/route')> }\n// }\n//\n// and `useEvents` reads a url's messages from it, so the hook and the route\n// cannot disagree about a message's shape.\n\n/** What a route module's GET yields, when it is `events(...)`; `unknown` for any other stream. */\nexport type EventsExportOf<M> = M extends {\n GET: { readonly \"~events\"?: infer S };\n}\n ? NonNullable<S> extends { yields: infer Y }\n ? Y\n : unknown\n : unknown;\n\ntype EventsMap = RegisterApi extends { events: infer M } ? M : {};\n\ntype Split<S extends string> = S extends `${infer A}/${infer B}`\n ? [A, ...Split<B>]\n : [S];\n\n/**\n * Whether a url's segments fit a pattern's, one segment at a time. Unlike\n * `Filled`, a `[id]` takes exactly one segment, so `/api/orders/42/events`\n * is `/api/orders/[id]/events` and not also `/api/orders/[id]`.\n */\ntype Fits<H extends string[], P extends string[]> = P extends [\n infer P0 extends string,\n ...infer PR extends string[],\n]\n ? P0 extends `[...${string}]`\n ? H extends [string, ...string[]]\n ? true\n : false\n : H extends [infer H0 extends string, ...infer HR extends string[]]\n ? P0 extends `[${string}]`\n ? Fits<HR, PR>\n : H0 extends P0\n ? Fits<HR, PR>\n : false\n : false\n : H extends []\n ? true\n : false;\n\n/** The api pattern a written url belongs to: `/api/orders/42/events` is `/api/orders/[id]/events`. */\ntype ApiPatternOf<H extends string> = ApiPattern extends infer P\n ? P extends string\n ? Fits<Split<StripQuery<H>>, Split<P>> extends true\n ? P\n : never\n : never\n : never;\n\n/**\n * Everything the stream at `H` yields, named events included. `unknown` when\n * `H` is not one api route the build found - a url computed at runtime, or\n * another site's - since there is nothing to read it from.\n */\nexport type EventsAt<H extends string> = NoApis extends true\n ? unknown\n : IsUnion<H> extends true\n ? unknown\n : [ApiPatternOf<H>] extends [never]\n ? unknown\n : ApiPatternOf<H> extends keyof EventsMap\n ? EventsMap[ApiPatternOf<H>]\n : unknown;\n\n/** A url `useEvents` may open: an api route this app answers, or another site's stream. */\nexport type EventsUrl = ApiRoute | `${string}://${string}`;\n\n// ── Search params, typed per route ───────────────────────────────────────────\n//\n// A page that exports a `searchParams` schema has said what its query string\n// means. The generated file records that schema per pattern:\n//\n// interface Register {\n// search: { '/search': SearchExportOf<typeof import('../src/app/search/page')> }\n// }\n//\n// and from there a link to `/search` is checked against the same schema the\n// page parses with — a `page` that must be a number is a number on the link,\n// a `q` the page requires is required to write the link, and a key the page\n// never reads does not compile. One schema, both ends. A route that exports\n// none takes anything; an href that is not a single route (computed, cast, or\n// off-site) takes anything too, because there is nothing to check it against.\n\n/** What a page module contributes: its `searchParams` export, or nothing. For the generated file. */\nexport type SearchExportOf<M> = M extends { searchParams: infer S }\n ? S\n : undefined;\n\ntype SearchMap = Register extends { search: infer M } ? M : {};\n\ntype StripQuery<H extends string> = H extends `${infer P}?${string}`\n ? P\n : H extends `${infer P}#${string}`\n ? P\n : H;\n\n/** The pattern a written href belongs to: `/posts/hello` is `/posts/[slug]`. */\ntype PatternOf<H extends string> = RoutePattern extends infer P\n ? P extends string\n ? StripQuery<H> extends Filled<P>\n ? P\n : never\n : never\n : never;\n\ntype IsUnion<T, U = T> = T extends unknown\n ? [U] extends [T]\n ? false\n : true\n : never;\n\ntype SchemaFor<P> = P extends keyof SearchMap ? SearchMap[P] : undefined;\n\ntype InputOf<S> = S extends { \"~standard\": { types?: { input: infer I } } }\n ? I\n : never;\ntype OutputOf<S> = S extends { \"~standard\": { types?: { output: infer O } } }\n ? O\n : never;\n\ntype OptionalKeys<T> = {\n [K in keyof T]-?: {} extends Pick<T, K> ? K : never;\n}[keyof T];\ntype RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>>;\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\n/**\n * What a link may write for a schema: the keys the schema's input requires\n * are required, the rest optional, and every value is the schema's OUTPUT\n * type. Output rather than input because `z.coerce.number()` takes `unknown`\n * in - that is what coercion means - and a link typed by it would accept\n * `page: 'two'`. The output is the number the page will actually see.\n */\ntype LinkInputOf<S> = Simplify<\n { [K in RequiredKeys<InputOf<S>> & keyof OutputOf<S>]: OutputOf<S>[K] } & {\n [K in OptionalKeys<InputOf<S>> & keyof OutputOf<S>]?: OutputOf<S>[K];\n }\n>;\n\ntype Scalar = string | number | boolean | null | undefined;\n\n/** What a link may carry when nothing declares otherwise. */\nexport type LooseSearch = Record<string, Scalar | readonly (string | number)[]>;\n\n/**\n * The search params a link to `H` may carry.\n *\n * The page's schema input when `H` is one declared route with a schema;\n * otherwise anything. \"One route\" matters: `path as Route` is every route at\n * once, and a link that could go anywhere cannot be held to one page's schema.\n */\nexport type SearchFor<H extends string> = Unregistered extends true\n ? LooseSearch\n : IsUnion<H> extends true\n ? LooseSearch\n : [PatternOf<H>] extends [never]\n ? LooseSearch\n : SchemaFor<PatternOf<H>> extends undefined\n ? LooseSearch\n : LinkInputOf<SchemaFor<PatternOf<H>>>;\n\n/**\n * The `search` prop, required exactly when the page's schema has a required\n * key. A page that needs `q` is not reachable without one, so the link that\n * omits it is the bug — caught here rather than on the page's error boundary.\n */\nexport type SearchProp<H extends string> =\n {} extends SearchFor<H>\n ? { search?: SearchFor<H> }\n : { search: SearchFor<H> };\n\n/** A query string from an object: scalars stringified, arrays repeated, null and undefined dropped. */\nexport function searchString(search: object): string {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(search)) {\n if (value === null || value === undefined) continue;\n\n if (Array.isArray(value)) {\n for (const item of value) params.append(key, String(item));\n } else {\n params.set(key, String(value));\n }\n }\n\n return params.toString();\n}\n\n/** `path` with `search` appended, keeping any query and hash already on it. */\nexport function withSearch(path: string, search: object | undefined): string {\n if (!search) return path;\n\n const hashAt = path.indexOf(\"#\");\n const hash = hashAt === -1 ? \"\" : path.slice(hashAt);\n const before = hashAt === -1 ? path : path.slice(0, hashAt);\n const queryAt = before.indexOf(\"?\");\n const base = queryAt === -1 ? before : before.slice(0, queryAt);\n const existing = queryAt === -1 ? \"\" : before.slice(queryAt + 1);\n const added = searchString(search);\n const query = [existing, added].filter(Boolean).join(\"&\");\n\n return query ? `${base}?${query}${hash}` : `${base}${hash}`;\n}\n\n/**\n * A typed url with its search params, for the places that take a string.\n *\n * visit(href('/search', { q: 'shoes', page: 2 }))\n *\n * `Link` has the same check on its own `search` prop. This is for `visit`,\n * `prefetch`, `redirect` and anything else that wants the finished string.\n */\nexport function href<H extends Route>(\n path: H,\n ...rest: {} extends SearchFor<H>\n ? [search?: SearchFor<H>]\n : [search: SearchFor<H>]\n): Route {\n return withSearch(path, rest[0] as object | undefined) as Route;\n}\n"]}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * What instrumentation.ts's onRequest() is told, once a response is over.
3
+ *
4
+ * "Over" is the part an app cannot see for itself: a page streams, so the
5
+ * handler has long returned when the last byte leaves, and a visitor who
6
+ * closes the tab mid-stream ends it early. Only the engine holds the body, so
7
+ * only the engine can say which happened, and when.
8
+ */
9
+ export interface ServedRequest {
10
+ method: string;
11
+ /** The url's path, never its query string: a query carries what people typed. */
12
+ pathname: string;
13
+ status: number;
14
+ /** From the request arriving to the last byte sent, or to the stream ending early. */
15
+ durationMs: number;
16
+ /** The client went away before the body was sent - a closed tab, a navigation elsewhere. */
17
+ aborted: boolean;
18
+ /** The render failed: the handler threw, or the body errored partway. */
19
+ error?: unknown;
20
+ /**
21
+ * Only the headers instrumentation.ts names in `onRequestHeaders`, by
22
+ * lowercase name, and only those the request had. Nothing else is passed:
23
+ * not cookies, not authorization.
24
+ */
25
+ headers: Readonly<Record<string, string>>;
26
+ }
27
+ export type OnRequest = (served: ServedRequest) => unknown;
28
+ /**
29
+ * Run the handler and call onRequest once the response it answers is over.
30
+ *
31
+ * The body is passed through rather than read, so streaming is untouched: each
32
+ * chunk goes out as it is produced. onRequest is never awaited and a throw
33
+ * from it is reported, not raised - a logger that fails must not fail the page.
34
+ */
35
+ export declare function observeServed(request: Request, serve: (request: Request) => Promise<Response>, onRequest: OnRequest, headerNames?: readonly string[]): Promise<Response>;