diff --git a/404.html b/404.html new file mode 100644 index 00000000..a944c751 --- /dev/null +++ b/404.html @@ -0,0 +1,20 @@ + + + + + + 404 | @jmondi/oauth2-server + + + + + + + + +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/adapters/index.html b/adapters/index.html new file mode 100644 index 00000000..48627bf1 --- /dev/null +++ b/adapters/index.html @@ -0,0 +1,31 @@ + + + + + + Adapters | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Adapters

Adapters are a set of helper functions to provide framework specific integration into @jmondi/oauth2-server. Currently, Express and Fastify are both supported.

Express

https://expressjs.com/

typescript
import {
+  requestFromExpress,
+  handleExpressResponse,
+  handleExpressError,
+} from "@jmondi/oauth2-server/express"
typescript
requestFromExpress(req: Express.Request): OAuthRequest;

Helper function to return an OAuthRequest from an Express.Request.

typescript
handleExpressResponse(expressResponse: Express.Response, oauthResponse: OAuthResponse): void;

Helper function that handles the express response after authorization.

typescript
handleExpressError(res: Express.Response, e: unknown | OAuthException): void;

Helper function that handles the express response if an error was thrown.

Fastify

https://www.fastify.io/

typescript
import {
+  requestFromFastify,
+  handleFastifyReply,
+  handleFastifyError,
+} from "@jmondi/oauth2-server/fastify"

The following functions are imported directly from the adapter instead of the root package.

typescript
requestFromFastify(req: FastifyRequest): OAuthRequest;

Helper function to return an OAuthRequest from an FastifyRequest.

typescript
handleFastifyReply(fastifyReply: FasitfyReply, oauthResponse: OAuthResponse): void;

Helper function that handles the express response after authorization.

typescript
handleFastifyError(reply: FasitfyReply, e: unknown | OAuthException): void;

Helper function that handles the express response if an error was thrown.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/assets/adapters_index.md.b69060b9.js b/assets/adapters_index.md.b69060b9.js new file mode 100644 index 00000000..67341212 --- /dev/null +++ b/assets/adapters_index.md.b69060b9.js @@ -0,0 +1,9 @@ +import{_ as s,o as a,c as e,O as p}from"./chunks/framework.2958c35d.js";const h=JSON.parse('{"title":"Adapters","description":"","frontmatter":{"title":"Adapters"},"headers":[],"relativePath":"adapters/index.md","filePath":"adapters/index.md"}'),n={name:"adapters/index.md"},t=p(`

Adapters

Adapters are a set of helper functions to provide framework specific integration into @jmondi/oauth2-server. Currently, Express and Fastify are both supported.

Express

https://expressjs.com/

typescript
import {
+  requestFromExpress,
+  handleExpressResponse,
+  handleExpressError,
+} from "@jmondi/oauth2-server/express"
typescript
requestFromExpress(req: Express.Request): OAuthRequest;

Helper function to return an OAuthRequest from an Express.Request.

typescript
handleExpressResponse(expressResponse: Express.Response, oauthResponse: OAuthResponse): void;

Helper function that handles the express response after authorization.

typescript
handleExpressError(res: Express.Response, e: unknown | OAuthException): void;

Helper function that handles the express response if an error was thrown.

Fastify

https://www.fastify.io/

typescript
import {
+  requestFromFastify,
+  handleFastifyReply,
+  handleFastifyError,
+} from "@jmondi/oauth2-server/fastify"

The following functions are imported directly from the adapter instead of the root package.

typescript
requestFromFastify(req: FastifyRequest): OAuthRequest;

Helper function to return an OAuthRequest from an FastifyRequest.

typescript
handleFastifyReply(fastifyReply: FasitfyReply, oauthResponse: OAuthResponse): void;

Helper function that handles the express response after authorization.

typescript
handleFastifyError(reply: FasitfyReply, e: unknown | OAuthException): void;

Helper function that handles the express response if an error was thrown.

`,21),o=[t];function l(r,c,i,y,d,F){return a(),e("div",null,o)}const A=s(n,[["render",l]]);export{h as __pageData,A as default}; diff --git a/assets/adapters_index.md.b69060b9.lean.js b/assets/adapters_index.md.b69060b9.lean.js new file mode 100644 index 00000000..47738112 --- /dev/null +++ b/assets/adapters_index.md.b69060b9.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as e,O as p}from"./chunks/framework.2958c35d.js";const h=JSON.parse('{"title":"Adapters","description":"","frontmatter":{"title":"Adapters"},"headers":[],"relativePath":"adapters/index.md","filePath":"adapters/index.md"}'),n={name:"adapters/index.md"},t=p("",21),o=[t];function l(r,c,i,y,d,F){return a(),e("div",null,o)}const A=s(n,[["render",l]]);export{h as __pageData,A as default}; diff --git a/assets/app.09493fed.js b/assets/app.09493fed.js new file mode 100644 index 00000000..9b2e1e6a --- /dev/null +++ b/assets/app.09493fed.js @@ -0,0 +1 @@ +import{K as s,a2 as p,a3 as i,a4 as u,a5 as c,a6 as l,a7 as d,a8 as f,a9 as m,aa as h,ab as A,ac as g,d as P,u as v,p as y,k as C,ad as w,ae as _,af as b,ag as E}from"./chunks/framework.2958c35d.js";import{t as R}from"./chunks/theme.d98fd9e6.js";function r(e){if(e.extends){const a=r(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const n=r(R),D=P({name:"VitePressApp",setup(){const{site:e}=v();return y(()=>{C(()=>{document.documentElement.lang=e.value.lang,document.documentElement.dir=e.value.dir})}),w(),_(),b(),n.setup&&n.setup(),()=>E(n.Layout)}});async function O(){const e=T(),a=S();a.provide(i,e);const t=u(e.route);return a.provide(c,t),a.component("Content",l),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),n.enhanceApp&&await n.enhanceApp({app:a,router:e,siteData:f}),{app:a,router:e,data:t}}function S(){return m(D)}function T(){let e=s,a;return h(t=>{let o=A(t);return e&&(a=o),(e||a===o)&&(o=o.replace(/\.js$/,".lean.js")),s&&(e=!1),g(()=>import(o),[])},n.NotFound)}s&&O().then(({app:e,router:a,data:t})=>{a.go().then(()=>{p(a.route,t.site),e.mount("#app")})});export{O as createApp}; diff --git a/assets/chunks/framework.2958c35d.js b/assets/chunks/framework.2958c35d.js new file mode 100644 index 00000000..fff86714 --- /dev/null +++ b/assets/chunks/framework.2958c35d.js @@ -0,0 +1,2 @@ +function Vn(e,t){const n=Object.create(null),s=e.split(",");for(let r=0;r!!n[r.toLowerCase()]:r=>!!n[r]}const te={},ft=[],Pe=()=>{},wi=()=>!1,Ci=/^on[^a-z]/,Nt=e=>Ci.test(e),qn=e=>e.startsWith("onUpdate:"),ie=Object.assign,zn=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Ei=Object.prototype.hasOwnProperty,q=(e,t)=>Ei.call(e,t),L=Array.isArray,at=e=>ln(e)==="[object Map]",ur=e=>ln(e)==="[object Set]",j=e=>typeof e=="function",se=e=>typeof e=="string",Yn=e=>typeof e=="symbol",ee=e=>e!==null&&typeof e=="object",dr=e=>ee(e)&&j(e.then)&&j(e.catch),hr=Object.prototype.toString,ln=e=>hr.call(e),Ti=e=>ln(e).slice(8,-1),pr=e=>ln(e)==="[object Object]",Jn=e=>se(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Et=Vn(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),cn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Ai=/-(\w)/g,Me=cn(e=>e.replace(Ai,(t,n)=>n?n.toUpperCase():"")),Ri=/\B([A-Z])/g,rt=cn(e=>e.replace(Ri,"-$1").toLowerCase()),fn=cn(e=>e.charAt(0).toUpperCase()+e.slice(1)),zt=cn(e=>e?`on${fn(e)}`:""),It=(e,t)=>!Object.is(e,t),Cn=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},Pi=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Ii=e=>{const t=se(e)?Number(e):NaN;return isNaN(t)?e:t};let xs;const Sn=()=>xs||(xs=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Xn(e){if(L(e)){const t={};for(let n=0;n{if(n){const s=n.split(Fi);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function Zn(e){let t="";if(se(e))t=e;else if(L(e))for(let n=0;nse(e)?e:e==null?"":L(e)||ee(e)&&(e.toString===hr||!j(e.toString))?JSON.stringify(e,mr,2):String(e),mr=(e,t)=>t&&t.__v_isRef?mr(e,t.value):at(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r])=>(n[`${s} =>`]=r,n),{})}:ur(t)?{[`Set(${t.size})`]:[...t.values()]}:ee(t)&&!L(t)&&!pr(t)?String(t):t;let _e;class Hi{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=_e,!t&&_e&&(this.index=(_e.scopes||(_e.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=_e;try{return _e=this,t()}finally{_e=n}}}on(){_e=this}off(){_e=this.parent}stop(t){if(this._active){let n,s;for(n=0,s=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},_r=e=>(e.w&Ve)>0,br=e=>(e.n&Ve)>0,ji=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let s=0;s{(d==="length"||d>=c)&&l.push(a)})}else switch(n!==void 0&&l.push(o.get(n)),t){case"add":L(e)?Jn(n)&&l.push(o.get("length")):(l.push(o.get(nt)),at(e)&&l.push(o.get(Ln)));break;case"delete":L(e)||(l.push(o.get(nt)),at(e)&&l.push(o.get(Ln)));break;case"set":at(e)&&l.push(o.get(nt));break}if(l.length===1)l[0]&&Nn(l[0]);else{const c=[];for(const a of l)a&&c.push(...a);Nn(Qn(c))}}function Nn(e,t){const n=L(e)?e:[...e];for(const s of n)s.computed&&Cs(s);for(const s of n)s.computed||Cs(s)}function Cs(e,t){(e!==Ae||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}function Di(e,t){var n;return(n=Qt.get(e))==null?void 0:n.get(t)}const Ki=Vn("__proto__,__v_isRef,__isVue"),xr=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Yn)),ki=es(),Wi=es(!1,!0),Vi=es(!0),Es=qi();function qi(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const s=z(this);for(let i=0,o=this.length;i{e[t]=function(...n){bt();const s=z(this)[t].apply(this,n);return yt(),s}}),e}function zi(e){const t=z(this);return pe(t,"has",e),t.hasOwnProperty(e)}function es(e=!1,t=!1){return function(s,r,i){if(r==="__v_isReactive")return!e;if(r==="__v_isReadonly")return e;if(r==="__v_isShallow")return t;if(r==="__v_raw"&&i===(e?t?fo:Ar:t?Tr:Er).get(s))return s;const o=L(s);if(!e){if(o&&q(Es,r))return Reflect.get(Es,r,i);if(r==="hasOwnProperty")return zi}const l=Reflect.get(s,r,i);return(Yn(r)?xr.has(r):Ki(r))||(e||pe(s,"get",r),t)?l:le(l)?o&&Jn(r)?l:l.value:ee(l)?e?Rr(l):un(l):l}}const Yi=wr(),Ji=wr(!0);function wr(e=!1){return function(n,s,r,i){let o=n[s];if(gt(o)&&le(o)&&!le(r))return!1;if(!e&&(!Gt(r)&&!gt(r)&&(o=z(o),r=z(r)),!L(n)&&le(o)&&!le(r)))return o.value=r,!0;const l=L(n)&&Jn(s)?Number(s)e,an=e=>Reflect.getPrototypeOf(e);function Ut(e,t,n=!1,s=!1){e=e.__v_raw;const r=z(e),i=z(t);n||(t!==i&&pe(r,"get",t),pe(r,"get",i));const{has:o}=an(r),l=s?ts:n?rs:Ot;if(o.call(r,t))return l(e.get(t));if(o.call(r,i))return l(e.get(i));e!==r&&e.get(t)}function jt(e,t=!1){const n=this.__v_raw,s=z(n),r=z(e);return t||(e!==r&&pe(s,"has",e),pe(s,"has",r)),e===r?n.has(e):n.has(e)||n.has(r)}function Bt(e,t=!1){return e=e.__v_raw,!t&&pe(z(e),"iterate",nt),Reflect.get(e,"size",e)}function Ts(e){e=z(e);const t=z(this);return an(t).has.call(t,e)||(t.add(e),He(t,"add",e,e)),this}function As(e,t){t=z(t);const n=z(this),{has:s,get:r}=an(n);let i=s.call(n,e);i||(e=z(e),i=s.call(n,e));const o=r.call(n,e);return n.set(e,t),i?It(t,o)&&He(n,"set",e,t):He(n,"add",e,t),this}function Rs(e){const t=z(this),{has:n,get:s}=an(t);let r=n.call(t,e);r||(e=z(e),r=n.call(t,e)),s&&s.call(t,e);const i=t.delete(e);return r&&He(t,"delete",e,void 0),i}function Ps(){const e=z(this),t=e.size!==0,n=e.clear();return t&&He(e,"clear",void 0,void 0),n}function Dt(e,t){return function(s,r){const i=this,o=i.__v_raw,l=z(o),c=t?ts:e?rs:Ot;return!e&&pe(l,"iterate",nt),o.forEach((a,d)=>s.call(r,c(a),c(d),i))}}function Kt(e,t,n){return function(...s){const r=this.__v_raw,i=z(r),o=at(i),l=e==="entries"||e===Symbol.iterator&&o,c=e==="keys"&&o,a=r[e](...s),d=n?ts:t?rs:Ot;return!t&&pe(i,"iterate",c?Ln:nt),{next(){const{value:p,done:y}=a.next();return y?{value:p,done:y}:{value:l?[d(p[0]),d(p[1])]:d(p),done:y}},[Symbol.iterator](){return this}}}}function Ue(e){return function(...t){return e==="delete"?!1:this}}function to(){const e={get(i){return Ut(this,i)},get size(){return Bt(this)},has:jt,add:Ts,set:As,delete:Rs,clear:Ps,forEach:Dt(!1,!1)},t={get(i){return Ut(this,i,!1,!0)},get size(){return Bt(this)},has:jt,add:Ts,set:As,delete:Rs,clear:Ps,forEach:Dt(!1,!0)},n={get(i){return Ut(this,i,!0)},get size(){return Bt(this,!0)},has(i){return jt.call(this,i,!0)},add:Ue("add"),set:Ue("set"),delete:Ue("delete"),clear:Ue("clear"),forEach:Dt(!0,!1)},s={get(i){return Ut(this,i,!0,!0)},get size(){return Bt(this,!0)},has(i){return jt.call(this,i,!0)},add:Ue("add"),set:Ue("set"),delete:Ue("delete"),clear:Ue("clear"),forEach:Dt(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(i=>{e[i]=Kt(i,!1,!1),n[i]=Kt(i,!0,!1),t[i]=Kt(i,!1,!0),s[i]=Kt(i,!0,!0)}),[e,n,t,s]}const[no,so,ro,io]=to();function ns(e,t){const n=t?e?io:ro:e?so:no;return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(q(n,r)&&r in s?n:s,r,i)}const oo={get:ns(!1,!1)},lo={get:ns(!1,!0)},co={get:ns(!0,!1)},Er=new WeakMap,Tr=new WeakMap,Ar=new WeakMap,fo=new WeakMap;function ao(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function uo(e){return e.__v_skip||!Object.isExtensible(e)?0:ao(Ti(e))}function un(e){return gt(e)?e:ss(e,!1,Cr,oo,Er)}function ho(e){return ss(e,!1,eo,lo,Tr)}function Rr(e){return ss(e,!0,Gi,co,Ar)}function ss(e,t,n,s,r){if(!ee(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=r.get(e);if(i)return i;const o=uo(e);if(o===0)return e;const l=new Proxy(e,o===2?s:n);return r.set(e,l),l}function ut(e){return gt(e)?ut(e.__v_raw):!!(e&&e.__v_isReactive)}function gt(e){return!!(e&&e.__v_isReadonly)}function Gt(e){return!!(e&&e.__v_isShallow)}function Pr(e){return ut(e)||gt(e)}function z(e){const t=e&&e.__v_raw;return t?z(t):e}function Tt(e){return Zt(e,"__v_skip",!0),e}const Ot=e=>ee(e)?un(e):e,rs=e=>ee(e)?Rr(e):e;function is(e){ke&&Ae&&(e=z(e),vr(e.dep||(e.dep=Qn())))}function os(e,t){e=z(e);const n=e.dep;n&&Nn(n)}function le(e){return!!(e&&e.__v_isRef===!0)}function ls(e){return Ir(e,!1)}function po(e){return Ir(e,!0)}function Ir(e,t){return le(e)?e:new go(e,t)}class go{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:z(t),this._value=n?t:Ot(t)}get value(){return is(this),this._value}set value(t){const n=this.__v_isShallow||Gt(t)||gt(t);t=n?t:z(t),It(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Ot(t),os(this))}}function mo(e){return le(e)?e.value:e}const _o={get:(e,t,n)=>mo(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return le(r)&&!le(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function Or(e){return ut(e)?e:new Proxy(e,_o)}class bo{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:s}=t(()=>is(this),()=>os(this));this._get=n,this._set=s}get value(){return this._get()}set value(t){this._set(t)}}function Sc(e){return new bo(e)}class yo{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Di(z(this._object),this._key)}}class vo{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function Mc(e,t,n){return le(e)?e:j(e)?new vo(e):ee(e)&&arguments.length>1?xo(e,t,n):ls(e)}function xo(e,t,n){const s=e[t];return le(s)?s:new yo(e,t,n)}class wo{constructor(t,n,s,r){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this._dirty=!0,this.effect=new Gn(t,()=>{this._dirty||(this._dirty=!0,os(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!r,this.__v_isReadonly=s}get value(){const t=z(this);return is(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function Co(e,t,n=!1){let s,r;const i=j(e);return i?(s=e,r=Pe):(s=e.get,r=e.set),new wo(s,r,i||!r,n)}function We(e,t,n,s){let r;try{r=s?e(...s):e()}catch(i){dn(i,t,n)}return r}function we(e,t,n,s){if(j(e)){const i=We(e,t,n,s);return i&&dr(i)&&i.catch(o=>{dn(o,t,n)}),i}const r=[];for(let i=0;i>>1;St(fe[s])Se&&fe.splice(t,1)}function Ro(e){L(e)?dt.push(...e):(!Ne||!Ne.includes(e,e.allowRecurse?Qe+1:Qe))&&dt.push(e),Mr()}function Is(e,t=Ft?Se+1:0){for(;tSt(n)-St(s)),Qe=0;Qee.id==null?1/0:e.id,Po=(e,t)=>{const n=St(e)-St(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Lr(e){Hn=!1,Ft=!0,fe.sort(Po);const t=Pe;try{for(Se=0;Sese(A)?A.trim():A)),p&&(r=n.map(Pi))}let l,c=s[l=zt(t)]||s[l=zt(Me(t))];!c&&i&&(c=s[l=zt(rt(t))]),c&&we(c,e,6,r);const a=s[l+"Once"];if(a){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,we(a,e,6,r)}}function Nr(e,t,n=!1){const s=t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let o={},l=!1;if(!j(e)){const c=a=>{const d=Nr(a,t,!0);d&&(l=!0,ie(o,d))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!l?(ee(e)&&s.set(e,null),null):(L(i)?i.forEach(c=>o[c]=null):ie(o,i),ee(e)&&s.set(e,o),o)}function hn(e,t){return!e||!Nt(t)?!1:(t=t.slice(2).replace(/Once$/,""),q(e,t[0].toLowerCase()+t.slice(1))||q(e,rt(t))||q(e,t))}let ae=null,pn=null;function tn(e){const t=ae;return ae=e,pn=e&&e.type.__scopeId||null,t}function Lc(e){pn=e}function Nc(){pn=null}function Oo(e,t=ae,n){if(!t||e._n)return e;const s=(...r)=>{s._d&&Ds(-1);const i=tn(t);let o;try{o=e(...r)}finally{tn(i),s._d&&Ds(1)}return o};return s._n=!0,s._c=!0,s._d=!0,s}function En(e){const{type:t,vnode:n,proxy:s,withProxy:r,props:i,propsOptions:[o],slots:l,attrs:c,emit:a,render:d,renderCache:p,data:y,setupState:A,ctx:$,inheritAttrs:O}=e;let D,b;const w=tn(e);try{if(n.shapeFlag&4){const R=r||s;D=Te(d.call(R,R,p,i,A,y,$)),b=c}else{const R=t;D=Te(R.length>1?R(i,{attrs:c,slots:l,emit:a}):R(i,null)),b=t.props?c:Fo(c)}}catch(R){Pt.length=0,dn(R,e,1),D=ce(be)}let N=D;if(b&&O!==!1){const R=Object.keys(b),{shapeFlag:K}=N;R.length&&K&7&&(o&&R.some(qn)&&(b=So(b,o)),N=qe(N,b))}return n.dirs&&(N=qe(N),N.dirs=N.dirs?N.dirs.concat(n.dirs):n.dirs),n.transition&&(N.transition=n.transition),D=N,tn(w),D}const Fo=e=>{let t;for(const n in e)(n==="class"||n==="style"||Nt(n))&&((t||(t={}))[n]=e[n]);return t},So=(e,t)=>{const n={};for(const s in e)(!qn(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function Mo(e,t,n){const{props:s,children:r,component:i}=e,{props:o,children:l,patchFlag:c}=t,a=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?Os(s,o,a):!!o;if(c&8){const d=t.dynamicProps;for(let p=0;pe.__isSuspense;function Hr(e,t){t&&t.pendingBranch?L(e)?t.effects.push(...e):t.effects.push(e):Ro(e)}function Ho(e,t){return gn(e,null,t)}function Hc(e,t){return gn(e,null,{flush:"post"})}const kt={};function Yt(e,t,n){return gn(e,t,n)}function gn(e,t,{immediate:n,deep:s,flush:r,onTrack:i,onTrigger:o}=te){var l;const c=Ui()===((l=oe)==null?void 0:l.scope)?oe:null;let a,d=!1,p=!1;if(le(e)?(a=()=>e.value,d=Gt(e)):ut(e)?(a=()=>e,s=!0):L(e)?(p=!0,d=e.some(R=>ut(R)||Gt(R)),a=()=>e.map(R=>{if(le(R))return R.value;if(ut(R))return ct(R);if(j(R))return We(R,c,2)})):j(e)?t?a=()=>We(e,c,2):a=()=>{if(!(c&&c.isUnmounted))return y&&y(),we(e,c,3,[A])}:a=Pe,t&&s){const R=a;a=()=>ct(R())}let y,A=R=>{y=w.onStop=()=>{We(R,c,4)}},$;if(Lt)if(A=Pe,t?n&&we(t,c,3,[a(),p?[]:void 0,A]):a(),r==="sync"){const R=Ol();$=R.__watcherHandles||(R.__watcherHandles=[])}else return Pe;let O=p?new Array(e.length).fill(kt):kt;const D=()=>{if(w.active)if(t){const R=w.run();(s||d||(p?R.some((K,J)=>It(K,O[J])):It(R,O)))&&(y&&y(),we(t,c,3,[R,O===kt?void 0:p&&O[0]===kt?[]:O,A]),O=R)}else w.run()};D.allowRecurse=!!t;let b;r==="sync"?b=D:r==="post"?b=()=>de(D,c&&c.suspense):(D.pre=!0,c&&(D.id=c.uid),b=()=>fs(D));const w=new Gn(a,b);t?n?D():O=w.run():r==="post"?de(w.run.bind(w),c&&c.suspense):w.run();const N=()=>{w.stop(),c&&c.scope&&zn(c.scope.effects,w)};return $&&$.push(N),N}function $o(e,t,n){const s=this.proxy,r=se(e)?e.includes(".")?$r(s,e):()=>s[e]:e.bind(s,s);let i;j(t)?i=t:(i=t.handler,n=t);const o=oe;_t(this);const l=gn(r,i.bind(s),n);return o?_t(o):st(),l}function $r(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;r{ct(n,t)});else if(pr(e))for(const n in e)ct(e[n],t);return e}function Fe(e,t,n,s){const r=e.dirs,i=t&&t.dirs;for(let o=0;o{e.isMounted=!0}),kr(()=>{e.isUnmounting=!0}),e}const ye=[Function,Array],Ur={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:ye,onEnter:ye,onAfterEnter:ye,onEnterCancelled:ye,onBeforeLeave:ye,onLeave:ye,onAfterLeave:ye,onLeaveCancelled:ye,onBeforeAppear:ye,onAppear:ye,onAfterAppear:ye,onAppearCancelled:ye},jo={name:"BaseTransition",props:Ur,setup(e,{slots:t}){const n=li(),s=Uo();let r;return()=>{const i=t.default&&Br(t.default(),!0);if(!i||!i.length)return;let o=i[0];if(i.length>1){for(const O of i)if(O.type!==be){o=O;break}}const l=z(e),{mode:c}=l;if(s.isLeaving)return Tn(o);const a=Fs(o);if(!a)return Tn(o);const d=$n(a,l,s,n);Un(a,d);const p=n.subTree,y=p&&Fs(p);let A=!1;const{getTransitionKey:$}=a.type;if($){const O=$();r===void 0?r=O:O!==r&&(r=O,A=!0)}if(y&&y.type!==be&&(!Ge(a,y)||A)){const O=$n(y,l,s,n);if(Un(y,O),c==="out-in")return s.isLeaving=!0,O.afterLeave=()=>{s.isLeaving=!1,n.update.active!==!1&&n.update()},Tn(o);c==="in-out"&&a.type!==be&&(O.delayLeave=(D,b,w)=>{const N=jr(s,y);N[String(y.key)]=y,D._leaveCb=()=>{b(),D._leaveCb=void 0,delete d.delayedLeave},d.delayedLeave=w})}return o}}},Bo=jo;function jr(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function $n(e,t,n,s){const{appear:r,mode:i,persisted:o=!1,onBeforeEnter:l,onEnter:c,onAfterEnter:a,onEnterCancelled:d,onBeforeLeave:p,onLeave:y,onAfterLeave:A,onLeaveCancelled:$,onBeforeAppear:O,onAppear:D,onAfterAppear:b,onAppearCancelled:w}=t,N=String(e.key),R=jr(n,e),K=(T,B)=>{T&&we(T,s,9,B)},J=(T,B)=>{const U=B[1];K(T,B),L(T)?T.every(Y=>Y.length<=1)&&U():T.length<=1&&U()},V={mode:i,persisted:o,beforeEnter(T){let B=l;if(!n.isMounted)if(r)B=O||l;else return;T._leaveCb&&T._leaveCb(!0);const U=R[N];U&&Ge(e,U)&&U.el._leaveCb&&U.el._leaveCb(),K(B,[T])},enter(T){let B=c,U=a,Y=d;if(!n.isMounted)if(r)B=D||c,U=b||a,Y=w||d;else return;let P=!1;const k=T._enterCb=F=>{P||(P=!0,F?K(Y,[T]):K(U,[T]),V.delayedLeave&&V.delayedLeave(),T._enterCb=void 0)};B?J(B,[T,k]):k()},leave(T,B){const U=String(e.key);if(T._enterCb&&T._enterCb(!0),n.isUnmounting)return B();K(p,[T]);let Y=!1;const P=T._leaveCb=k=>{Y||(Y=!0,B(),k?K($,[T]):K(A,[T]),T._leaveCb=void 0,R[U]===e&&delete R[U])};R[U]=e,y?J(y,[T,P]):P()},clone(T){return $n(T,t,n,s)}};return V}function Tn(e){if(mn(e))return e=qe(e),e.children=null,e}function Fs(e){return mn(e)?e.children?e.children[0]:void 0:e}function Un(e,t){e.shapeFlag&6&&e.component?Un(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Br(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;iie({name:e.name},t,{setup:e}))():e}const ht=e=>!!e.type.__asyncLoader,mn=e=>e.type.__isKeepAlive;function Do(e,t){Kr(e,"a",t)}function Ko(e,t){Kr(e,"da",t)}function Kr(e,t,n=oe){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(_n(t,s,n),n){let r=n.parent;for(;r&&r.parent;)mn(r.parent.vnode)&&ko(s,t,n,r),r=r.parent}}function ko(e,t,n,s){const r=_n(t,e,s,!0);yn(()=>{zn(s[t],r)},n)}function _n(e,t,n=oe,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...o)=>{if(n.isUnmounted)return;bt(),_t(n);const l=we(t,n,e,o);return st(),yt(),l});return s?r.unshift(i):r.push(i),i}}const $e=e=>(t,n=oe)=>(!Lt||e==="sp")&&_n(e,(...s)=>t(...s),n),Wo=$e("bm"),bn=$e("m"),Vo=$e("bu"),qo=$e("u"),kr=$e("bum"),yn=$e("um"),zo=$e("sp"),Yo=$e("rtg"),Jo=$e("rtc");function Xo(e,t=oe){_n("ec",e,t)}const as="components";function $c(e,t){return Vr(as,e,!0,t)||e}const Wr=Symbol.for("v-ndc");function Uc(e){return se(e)?Vr(as,e,!1)||e:e||Wr}function Vr(e,t,n=!0,s=!1){const r=ae||oe;if(r){const i=r.type;if(e===as){const l=Rl(i,!1);if(l&&(l===t||l===Me(t)||l===fn(Me(t))))return i}const o=Ss(r[e]||i[e],t)||Ss(r.appContext[e],t);return!o&&s?i:o}}function Ss(e,t){return e&&(e[t]||e[Me(t)]||e[fn(Me(t))])}function jc(e,t,n,s){let r;const i=n&&n[s];if(L(e)||se(e)){r=new Array(e.length);for(let o=0,l=e.length;ot(o,l,void 0,i&&i[l]));else{const o=Object.keys(e);r=new Array(o.length);for(let l=0,c=o.length;lon(t)?!(t.type===be||t.type===he&&!qr(t.children)):!0)?e:null}function Dc(e,t){const n={};for(const s in e)n[t&&/[A-Z]/.test(s)?`on:${s}`:zt(s)]=e[s];return n}const jn=e=>e?ci(e)?gs(e)||e.proxy:jn(e.parent):null,At=ie(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>jn(e.parent),$root:e=>jn(e.root),$emit:e=>e.emit,$options:e=>us(e),$forceUpdate:e=>e.f||(e.f=()=>fs(e.update)),$nextTick:e=>e.n||(e.n=Sr.bind(e.proxy)),$watch:e=>$o.bind(e)}),An=(e,t)=>e!==te&&!e.__isScriptSetup&&q(e,t),Zo={get({_:e},t){const{ctx:n,setupState:s,data:r,props:i,accessCache:o,type:l,appContext:c}=e;let a;if(t[0]!=="$"){const A=o[t];if(A!==void 0)switch(A){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(An(s,t))return o[t]=1,s[t];if(r!==te&&q(r,t))return o[t]=2,r[t];if((a=e.propsOptions[0])&&q(a,t))return o[t]=3,i[t];if(n!==te&&q(n,t))return o[t]=4,n[t];Bn&&(o[t]=0)}}const d=At[t];let p,y;if(d)return t==="$attrs"&&pe(e,"get",t),d(e);if((p=l.__cssModules)&&(p=p[t]))return p;if(n!==te&&q(n,t))return o[t]=4,n[t];if(y=c.config.globalProperties,q(y,t))return y[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return An(r,t)?(r[t]=n,!0):s!==te&&q(s,t)?(s[t]=n,!0):q(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,propsOptions:i}},o){let l;return!!n[o]||e!==te&&q(e,o)||An(t,o)||(l=i[0])&&q(l,o)||q(s,o)||q(At,o)||q(r.config.globalProperties,o)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:q(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Kc(){return Qo().slots}function Qo(){const e=li();return e.setupContext||(e.setupContext=ai(e))}function Ms(e){return L(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Bn=!0;function Go(e){const t=us(e),n=e.proxy,s=e.ctx;Bn=!1,t.beforeCreate&&Ls(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:o,watch:l,provide:c,inject:a,created:d,beforeMount:p,mounted:y,beforeUpdate:A,updated:$,activated:O,deactivated:D,beforeDestroy:b,beforeUnmount:w,destroyed:N,unmounted:R,render:K,renderTracked:J,renderTriggered:V,errorCaptured:T,serverPrefetch:B,expose:U,inheritAttrs:Y,components:P,directives:k,filters:F}=t;if(a&&el(a,s,null),o)for(const ne in o){const Q=o[ne];j(Q)&&(s[ne]=Q.bind(n))}if(r){const ne=r.call(n,n);ee(ne)&&(e.data=un(ne))}if(Bn=!0,i)for(const ne in i){const Q=i[ne],ze=j(Q)?Q.bind(n,n):j(Q.get)?Q.get.bind(n,n):Pe,Ht=!j(Q)&&j(Q.set)?Q.set.bind(n):Pe,Ye=Ee({get:ze,set:Ht});Object.defineProperty(s,ne,{enumerable:!0,configurable:!0,get:()=>Ye.value,set:Ie=>Ye.value=Ie})}if(l)for(const ne in l)zr(l[ne],s,n,ne);if(c){const ne=j(c)?c.call(n):c;Reflect.ownKeys(ne).forEach(Q=>{ol(Q,ne[Q])})}d&&Ls(d,e,"c");function X(ne,Q){L(Q)?Q.forEach(ze=>ne(ze.bind(n))):Q&&ne(Q.bind(n))}if(X(Wo,p),X(bn,y),X(Vo,A),X(qo,$),X(Do,O),X(Ko,D),X(Xo,T),X(Jo,J),X(Yo,V),X(kr,w),X(yn,R),X(zo,B),L(U))if(U.length){const ne=e.exposed||(e.exposed={});U.forEach(Q=>{Object.defineProperty(ne,Q,{get:()=>n[Q],set:ze=>n[Q]=ze})})}else e.exposed||(e.exposed={});K&&e.render===Pe&&(e.render=K),Y!=null&&(e.inheritAttrs=Y),P&&(e.components=P),k&&(e.directives=k)}function el(e,t,n=Pe){L(e)&&(e=Dn(e));for(const s in e){const r=e[s];let i;ee(r)?"default"in r?i=pt(r.from||s,r.default,!0):i=pt(r.from||s):i=pt(r),le(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:o=>i.value=o}):t[s]=i}}function Ls(e,t,n){we(L(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function zr(e,t,n,s){const r=s.includes(".")?$r(n,s):()=>n[s];if(se(e)){const i=t[e];j(i)&&Yt(r,i)}else if(j(e))Yt(r,e.bind(n));else if(ee(e))if(L(e))e.forEach(i=>zr(i,t,n,s));else{const i=j(e.handler)?e.handler.bind(n):t[e.handler];j(i)&&Yt(r,i,e)}}function us(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:o}}=e.appContext,l=i.get(t);let c;return l?c=l:!r.length&&!n&&!s?c=t:(c={},r.length&&r.forEach(a=>nn(c,a,o,!0)),nn(c,t,o)),ee(t)&&i.set(t,c),c}function nn(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&nn(e,i,n,!0),r&&r.forEach(o=>nn(e,o,n,!0));for(const o in t)if(!(s&&o==="expose")){const l=tl[o]||n&&n[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const tl={data:Ns,props:Hs,emits:Hs,methods:Ct,computed:Ct,beforeCreate:ue,created:ue,beforeMount:ue,mounted:ue,beforeUpdate:ue,updated:ue,beforeDestroy:ue,beforeUnmount:ue,destroyed:ue,unmounted:ue,activated:ue,deactivated:ue,errorCaptured:ue,serverPrefetch:ue,components:Ct,directives:Ct,watch:sl,provide:Ns,inject:nl};function Ns(e,t){return t?e?function(){return ie(j(e)?e.call(this,this):e,j(t)?t.call(this,this):t)}:t:e}function nl(e,t){return Ct(Dn(e),Dn(t))}function Dn(e){if(L(e)){const t={};for(let n=0;n1)return n&&j(t)?t.call(s&&s.proxy):t}}function ll(e,t,n,s=!1){const r={},i={};Zt(i,vn,1),e.propsDefaults=Object.create(null),Jr(e,t,r,i);for(const o in e.propsOptions[0])o in r||(r[o]=void 0);n?e.props=s?r:ho(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function cl(e,t,n,s){const{props:r,attrs:i,vnode:{patchFlag:o}}=e,l=z(r),[c]=e.propsOptions;let a=!1;if((s||o>0)&&!(o&16)){if(o&8){const d=e.vnode.dynamicProps;for(let p=0;p{c=!0;const[y,A]=Xr(p,t,!0);ie(o,y),A&&l.push(...A)};!n&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!i&&!c)return ee(e)&&s.set(e,ft),ft;if(L(i))for(let d=0;d-1,A[1]=O<0||$-1||q(A,"default"))&&l.push(p)}}}const a=[o,l];return ee(e)&&s.set(e,a),a}function $s(e){return e[0]!=="$"}function Us(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function js(e,t){return Us(e)===Us(t)}function Bs(e,t){return L(t)?t.findIndex(n=>js(n,e)):j(t)&&js(t,e)?0:-1}const Zr=e=>e[0]==="_"||e==="$stable",ds=e=>L(e)?e.map(Te):[Te(e)],fl=(e,t,n)=>{if(t._n)return t;const s=Oo((...r)=>ds(t(...r)),n);return s._c=!1,s},Qr=(e,t,n)=>{const s=e._ctx;for(const r in e){if(Zr(r))continue;const i=e[r];if(j(i))t[r]=fl(r,i,s);else if(i!=null){const o=ds(i);t[r]=()=>o}}},Gr=(e,t)=>{const n=ds(t);e.slots.default=()=>n},al=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=z(t),Zt(t,"_",n)):Qr(t,e.slots={})}else e.slots={},t&&Gr(e,t);Zt(e.slots,vn,1)},ul=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,o=te;if(s.shapeFlag&32){const l=t._;l?n&&l===1?i=!1:(ie(r,t),!n&&l===1&&delete r._):(i=!t.$stable,Qr(t,r)),o=t}else t&&(Gr(e,t),o={default:1});if(i)for(const l in r)!Zr(l)&&!(l in o)&&delete r[l]};function rn(e,t,n,s,r=!1){if(L(e)){e.forEach((y,A)=>rn(y,t&&(L(t)?t[A]:t),n,s,r));return}if(ht(s)&&!r)return;const i=s.shapeFlag&4?gs(s.component)||s.component.proxy:s.el,o=r?null:i,{i:l,r:c}=e,a=t&&t.r,d=l.refs===te?l.refs={}:l.refs,p=l.setupState;if(a!=null&&a!==c&&(se(a)?(d[a]=null,q(p,a)&&(p[a]=null)):le(a)&&(a.value=null)),j(c))We(c,l,12,[o,d]);else{const y=se(c),A=le(c);if(y||A){const $=()=>{if(e.f){const O=y?q(p,c)?p[c]:d[c]:c.value;r?L(O)&&zn(O,i):L(O)?O.includes(i)||O.push(i):y?(d[c]=[i],q(p,c)&&(p[c]=d[c])):(c.value=[i],e.k&&(d[e.k]=c.value))}else y?(d[c]=o,q(p,c)&&(p[c]=o)):A&&(c.value=o,e.k&&(d[e.k]=o))};o?($.id=-1,de($,n)):$()}}}let je=!1;const Wt=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",Vt=e=>e.nodeType===8;function dl(e){const{mt:t,p:n,o:{patchProp:s,createText:r,nextSibling:i,parentNode:o,remove:l,insert:c,createComment:a}}=e,d=(b,w)=>{if(!w.hasChildNodes()){n(null,b,w),en(),w._vnode=b;return}je=!1,p(w.firstChild,b,null,null,null),en(),w._vnode=b,je&&console.error("Hydration completed but contains mismatches.")},p=(b,w,N,R,K,J=!1)=>{const V=Vt(b)&&b.data==="[",T=()=>O(b,w,N,R,K,V),{type:B,ref:U,shapeFlag:Y,patchFlag:P}=w;let k=b.nodeType;w.el=b,P===-2&&(J=!1,w.dynamicChildren=null);let F=null;switch(B){case mt:k!==3?w.children===""?(c(w.el=r(""),o(b),b),F=b):F=T():(b.data!==w.children&&(je=!0,b.data=w.children),F=i(b));break;case be:k!==8||V?F=T():F=i(b);break;case Rt:if(V&&(b=i(b),k=b.nodeType),k===1||k===3){F=b;const ge=!w.children.length;for(let X=0;X{J=J||!!w.dynamicChildren;const{type:V,props:T,patchFlag:B,shapeFlag:U,dirs:Y}=w,P=V==="input"&&Y||V==="option";if(P||B!==-1){if(Y&&Fe(w,null,N,"created"),T)if(P||!J||B&48)for(const F in T)(P&&F.endsWith("value")||Nt(F)&&!Et(F))&&s(b,F,null,T[F],!1,void 0,N);else T.onClick&&s(b,"onClick",null,T.onClick,!1,void 0,N);let k;if((k=T&&T.onVnodeBeforeMount)&&ve(k,N,w),Y&&Fe(w,null,N,"beforeMount"),((k=T&&T.onVnodeMounted)||Y)&&Hr(()=>{k&&ve(k,N,w),Y&&Fe(w,null,N,"mounted")},R),U&16&&!(T&&(T.innerHTML||T.textContent))){let F=A(b.firstChild,w,b,N,R,K,J);for(;F;){je=!0;const ge=F;F=F.nextSibling,l(ge)}}else U&8&&b.textContent!==w.children&&(je=!0,b.textContent=w.children)}return b.nextSibling},A=(b,w,N,R,K,J,V)=>{V=V||!!w.dynamicChildren;const T=w.children,B=T.length;for(let U=0;U{const{slotScopeIds:V}=w;V&&(K=K?K.concat(V):V);const T=o(b),B=A(i(b),w,T,N,R,K,J);return B&&Vt(B)&&B.data==="]"?i(w.anchor=B):(je=!0,c(w.anchor=a("]"),T,B),B)},O=(b,w,N,R,K,J)=>{if(je=!0,w.el=null,J){const B=D(b);for(;;){const U=i(b);if(U&&U!==B)l(U);else break}}const V=i(b),T=o(b);return l(b),n(null,w,T,V,N,R,Wt(T),K),V},D=b=>{let w=0;for(;b;)if(b=i(b),b&&Vt(b)&&(b.data==="["&&w++,b.data==="]")){if(w===0)return i(b);w--}return b};return[d,p]}const de=Hr;function hl(e){return pl(e,dl)}function pl(e,t){const n=Sn();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:c,setText:a,setElementText:d,parentNode:p,nextSibling:y,setScopeId:A=Pe,insertStaticContent:$}=e,O=(f,u,h,m=null,g=null,x=null,E=!1,v=null,C=!!u.dynamicChildren)=>{if(f===u)return;f&&!Ge(f,u)&&(m=$t(f),Ie(f,g,x,!0),f=null),u.patchFlag===-2&&(C=!1,u.dynamicChildren=null);const{type:_,ref:S,shapeFlag:I}=u;switch(_){case mt:D(f,u,h,m);break;case be:b(f,u,h,m);break;case Rt:f==null&&w(u,h,m,E);break;case he:P(f,u,h,m,g,x,E,v,C);break;default:I&1?K(f,u,h,m,g,x,E,v,C):I&6?k(f,u,h,m,g,x,E,v,C):(I&64||I&128)&&_.process(f,u,h,m,g,x,E,v,C,it)}S!=null&&g&&rn(S,f&&f.ref,x,u||f,!u)},D=(f,u,h,m)=>{if(f==null)s(u.el=l(u.children),h,m);else{const g=u.el=f.el;u.children!==f.children&&a(g,u.children)}},b=(f,u,h,m)=>{f==null?s(u.el=c(u.children||""),h,m):u.el=f.el},w=(f,u,h,m)=>{[f.el,f.anchor]=$(f.children,u,h,m,f.el,f.anchor)},N=({el:f,anchor:u},h,m)=>{let g;for(;f&&f!==u;)g=y(f),s(f,h,m),f=g;s(u,h,m)},R=({el:f,anchor:u})=>{let h;for(;f&&f!==u;)h=y(f),r(f),f=h;r(u)},K=(f,u,h,m,g,x,E,v,C)=>{E=E||u.type==="svg",f==null?J(u,h,m,g,x,E,v,C):B(f,u,g,x,E,v,C)},J=(f,u,h,m,g,x,E,v)=>{let C,_;const{type:S,props:I,shapeFlag:M,transition:H,dirs:W}=f;if(C=f.el=o(f.type,x,I&&I.is,I),M&8?d(C,f.children):M&16&&T(f.children,C,null,m,g,x&&S!=="foreignObject",E,v),W&&Fe(f,null,m,"created"),V(C,f,f.scopeId,E,m),I){for(const Z in I)Z!=="value"&&!Et(Z)&&i(C,Z,null,I[Z],x,f.children,m,g,Le);"value"in I&&i(C,"value",null,I.value),(_=I.onVnodeBeforeMount)&&ve(_,m,f)}W&&Fe(f,null,m,"beforeMount");const G=(!g||g&&!g.pendingBranch)&&H&&!H.persisted;G&&H.beforeEnter(C),s(C,u,h),((_=I&&I.onVnodeMounted)||G||W)&&de(()=>{_&&ve(_,m,f),G&&H.enter(C),W&&Fe(f,null,m,"mounted")},g)},V=(f,u,h,m,g)=>{if(h&&A(f,h),m)for(let x=0;x{for(let _=C;_{const v=u.el=f.el;let{patchFlag:C,dynamicChildren:_,dirs:S}=u;C|=f.patchFlag&16;const I=f.props||te,M=u.props||te;let H;h&&Je(h,!1),(H=M.onVnodeBeforeUpdate)&&ve(H,h,u,f),S&&Fe(u,f,h,"beforeUpdate"),h&&Je(h,!0);const W=g&&u.type!=="foreignObject";if(_?U(f.dynamicChildren,_,v,h,m,W,x):E||Q(f,u,v,null,h,m,W,x,!1),C>0){if(C&16)Y(v,u,I,M,h,m,g);else if(C&2&&I.class!==M.class&&i(v,"class",null,M.class,g),C&4&&i(v,"style",I.style,M.style,g),C&8){const G=u.dynamicProps;for(let Z=0;Z{H&&ve(H,h,u,f),S&&Fe(u,f,h,"updated")},m)},U=(f,u,h,m,g,x,E)=>{for(let v=0;v{if(h!==m){if(h!==te)for(const v in h)!Et(v)&&!(v in m)&&i(f,v,h[v],null,E,u.children,g,x,Le);for(const v in m){if(Et(v))continue;const C=m[v],_=h[v];C!==_&&v!=="value"&&i(f,v,_,C,E,u.children,g,x,Le)}"value"in m&&i(f,"value",h.value,m.value)}},P=(f,u,h,m,g,x,E,v,C)=>{const _=u.el=f?f.el:l(""),S=u.anchor=f?f.anchor:l("");let{patchFlag:I,dynamicChildren:M,slotScopeIds:H}=u;H&&(v=v?v.concat(H):H),f==null?(s(_,h,m),s(S,h,m),T(u.children,h,S,g,x,E,v,C)):I>0&&I&64&&M&&f.dynamicChildren?(U(f.dynamicChildren,M,h,g,x,E,v),(u.key!=null||g&&u===g.subTree)&&ei(f,u,!0)):Q(f,u,h,S,g,x,E,v,C)},k=(f,u,h,m,g,x,E,v,C)=>{u.slotScopeIds=v,f==null?u.shapeFlag&512?g.ctx.activate(u,h,m,E,C):F(u,h,m,g,x,E,C):ge(f,u,C)},F=(f,u,h,m,g,x,E)=>{const v=f.component=Cl(f,m,g);if(mn(f)&&(v.ctx.renderer=it),El(v),v.asyncDep){if(g&&g.registerDep(v,X),!f.el){const C=v.subTree=ce(be);b(null,C,u,h)}return}X(v,f,u,h,g,x,E)},ge=(f,u,h)=>{const m=u.component=f.component;if(Mo(f,u,h))if(m.asyncDep&&!m.asyncResolved){ne(m,u,h);return}else m.next=u,Ao(m.update),m.update();else u.el=f.el,m.vnode=u},X=(f,u,h,m,g,x,E)=>{const v=()=>{if(f.isMounted){let{next:S,bu:I,u:M,parent:H,vnode:W}=f,G=S,Z;Je(f,!1),S?(S.el=W.el,ne(f,S,E)):S=W,I&&Cn(I),(Z=S.props&&S.props.onVnodeBeforeUpdate)&&ve(Z,H,S,W),Je(f,!0);const re=En(f),Ce=f.subTree;f.subTree=re,O(Ce,re,p(Ce.el),$t(Ce),f,g,x),S.el=re.el,G===null&&Lo(f,re.el),M&&de(M,g),(Z=S.props&&S.props.onVnodeUpdated)&&de(()=>ve(Z,H,S,W),g)}else{let S;const{el:I,props:M}=u,{bm:H,m:W,parent:G}=f,Z=ht(u);if(Je(f,!1),H&&Cn(H),!Z&&(S=M&&M.onVnodeBeforeMount)&&ve(S,G,u),Je(f,!0),I&&wn){const re=()=>{f.subTree=En(f),wn(I,f.subTree,f,g,null)};Z?u.type.__asyncLoader().then(()=>!f.isUnmounted&&re()):re()}else{const re=f.subTree=En(f);O(null,re,h,m,f,g,x),u.el=re.el}if(W&&de(W,g),!Z&&(S=M&&M.onVnodeMounted)){const re=u;de(()=>ve(S,G,re),g)}(u.shapeFlag&256||G&&ht(G.vnode)&&G.vnode.shapeFlag&256)&&f.a&&de(f.a,g),f.isMounted=!0,u=h=m=null}},C=f.effect=new Gn(v,()=>fs(_),f.scope),_=f.update=()=>C.run();_.id=f.uid,Je(f,!0),_()},ne=(f,u,h)=>{u.component=f;const m=f.vnode.props;f.vnode=u,f.next=null,cl(f,u.props,m,h),ul(f,u.children,h),bt(),Is(),yt()},Q=(f,u,h,m,g,x,E,v,C=!1)=>{const _=f&&f.children,S=f?f.shapeFlag:0,I=u.children,{patchFlag:M,shapeFlag:H}=u;if(M>0){if(M&128){Ht(_,I,h,m,g,x,E,v,C);return}else if(M&256){ze(_,I,h,m,g,x,E,v,C);return}}H&8?(S&16&&Le(_,g,x),I!==_&&d(h,I)):S&16?H&16?Ht(_,I,h,m,g,x,E,v,C):Le(_,g,x,!0):(S&8&&d(h,""),H&16&&T(I,h,m,g,x,E,v,C))},ze=(f,u,h,m,g,x,E,v,C)=>{f=f||ft,u=u||ft;const _=f.length,S=u.length,I=Math.min(_,S);let M;for(M=0;MS?Le(f,g,x,!0,!1,I):T(u,h,m,g,x,E,v,C,I)},Ht=(f,u,h,m,g,x,E,v,C)=>{let _=0;const S=u.length;let I=f.length-1,M=S-1;for(;_<=I&&_<=M;){const H=f[_],W=u[_]=C?Ke(u[_]):Te(u[_]);if(Ge(H,W))O(H,W,h,null,g,x,E,v,C);else break;_++}for(;_<=I&&_<=M;){const H=f[I],W=u[M]=C?Ke(u[M]):Te(u[M]);if(Ge(H,W))O(H,W,h,null,g,x,E,v,C);else break;I--,M--}if(_>I){if(_<=M){const H=M+1,W=HM)for(;_<=I;)Ie(f[_],g,x,!0),_++;else{const H=_,W=_,G=new Map;for(_=W;_<=M;_++){const me=u[_]=C?Ke(u[_]):Te(u[_]);me.key!=null&&G.set(me.key,_)}let Z,re=0;const Ce=M-W+1;let ot=!1,bs=0;const vt=new Array(Ce);for(_=0;_=Ce){Ie(me,g,x,!0);continue}let Oe;if(me.key!=null)Oe=G.get(me.key);else for(Z=W;Z<=M;Z++)if(vt[Z-W]===0&&Ge(me,u[Z])){Oe=Z;break}Oe===void 0?Ie(me,g,x,!0):(vt[Oe-W]=_+1,Oe>=bs?bs=Oe:ot=!0,O(me,u[Oe],h,null,g,x,E,v,C),re++)}const ys=ot?gl(vt):ft;for(Z=ys.length-1,_=Ce-1;_>=0;_--){const me=W+_,Oe=u[me],vs=me+1{const{el:x,type:E,transition:v,children:C,shapeFlag:_}=f;if(_&6){Ye(f.component.subTree,u,h,m);return}if(_&128){f.suspense.move(u,h,m);return}if(_&64){E.move(f,u,h,it);return}if(E===he){s(x,u,h);for(let I=0;Iv.enter(x),g);else{const{leave:I,delayLeave:M,afterLeave:H}=v,W=()=>s(x,u,h),G=()=>{I(x,()=>{W(),H&&H()})};M?M(x,W,G):G()}else s(x,u,h)},Ie=(f,u,h,m=!1,g=!1)=>{const{type:x,props:E,ref:v,children:C,dynamicChildren:_,shapeFlag:S,patchFlag:I,dirs:M}=f;if(v!=null&&rn(v,null,h,f,!0),S&256){u.ctx.deactivate(f);return}const H=S&1&&M,W=!ht(f);let G;if(W&&(G=E&&E.onVnodeBeforeUnmount)&&ve(G,u,f),S&6)xi(f.component,h,m);else{if(S&128){f.suspense.unmount(h,m);return}H&&Fe(f,null,u,"beforeUnmount"),S&64?f.type.remove(f,u,h,g,it,m):_&&(x!==he||I>0&&I&64)?Le(_,u,h,!1,!0):(x===he&&I&384||!g&&S&16)&&Le(C,u,h),m&&ms(f)}(W&&(G=E&&E.onVnodeUnmounted)||H)&&de(()=>{G&&ve(G,u,f),H&&Fe(f,null,u,"unmounted")},h)},ms=f=>{const{type:u,el:h,anchor:m,transition:g}=f;if(u===he){vi(h,m);return}if(u===Rt){R(f);return}const x=()=>{r(h),g&&!g.persisted&&g.afterLeave&&g.afterLeave()};if(f.shapeFlag&1&&g&&!g.persisted){const{leave:E,delayLeave:v}=g,C=()=>E(h,x);v?v(f.el,x,C):C()}else x()},vi=(f,u)=>{let h;for(;f!==u;)h=y(f),r(f),f=h;r(u)},xi=(f,u,h)=>{const{bum:m,scope:g,update:x,subTree:E,um:v}=f;m&&Cn(m),g.stop(),x&&(x.active=!1,Ie(E,f,u,h)),v&&de(v,u),de(()=>{f.isUnmounted=!0},u),u&&u.pendingBranch&&!u.isUnmounted&&f.asyncDep&&!f.asyncResolved&&f.suspenseId===u.pendingId&&(u.deps--,u.deps===0&&u.resolve())},Le=(f,u,h,m=!1,g=!1,x=0)=>{for(let E=x;Ef.shapeFlag&6?$t(f.component.subTree):f.shapeFlag&128?f.suspense.next():y(f.anchor||f.el),_s=(f,u,h)=>{f==null?u._vnode&&Ie(u._vnode,null,null,!0):O(u._vnode||null,f,u,null,null,null,h),Is(),en(),u._vnode=f},it={p:O,um:Ie,m:Ye,r:ms,mt:F,mc:T,pc:Q,pbc:U,n:$t,o:e};let xn,wn;return t&&([xn,wn]=t(it)),{render:_s,hydrate:xn,createApp:il(_s,xn)}}function Je({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function ei(e,t,n=!1){const s=e.children,r=t.children;if(L(s)&&L(r))for(let i=0;i>1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}const ml=e=>e.__isTeleport,he=Symbol.for("v-fgt"),mt=Symbol.for("v-txt"),be=Symbol.for("v-cmt"),Rt=Symbol.for("v-stc"),Pt=[];let Re=null;function ti(e=!1){Pt.push(Re=e?null:[])}function _l(){Pt.pop(),Re=Pt[Pt.length-1]||null}let Mt=1;function Ds(e){Mt+=e}function ni(e){return e.dynamicChildren=Mt>0?Re||ft:null,_l(),Mt>0&&Re&&Re.push(e),e}function kc(e,t,n,s,r,i){return ni(ii(e,t,n,s,r,i,!0))}function si(e,t,n,s,r){return ni(ce(e,t,n,s,r,!0))}function on(e){return e?e.__v_isVNode===!0:!1}function Ge(e,t){return e.type===t.type&&e.key===t.key}const vn="__vInternal",ri=({key:e})=>e??null,Jt=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?se(e)||le(e)||j(e)?{i:ae,r:e,k:t,f:!!n}:e:null);function ii(e,t=null,n=null,s=0,r=null,i=e===he?0:1,o=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ri(t),ref:t&&Jt(t),scopeId:pn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:ae};return l?(hs(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=se(n)?8:16),Mt>0&&!o&&Re&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&Re.push(c),c}const ce=bl;function bl(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===Wr)&&(e=be),on(e)){const l=qe(e,t,!0);return n&&hs(l,n),Mt>0&&!i&&Re&&(l.shapeFlag&6?Re[Re.indexOf(e)]=l:Re.push(l)),l.patchFlag|=-2,l}if(Pl(e)&&(e=e.__vccOpts),t){t=yl(t);let{class:l,style:c}=t;l&&!se(l)&&(t.class=Zn(l)),ee(c)&&(Pr(c)&&!L(c)&&(c=ie({},c)),t.style=Xn(c))}const o=se(e)?1:No(e)?128:ml(e)?64:ee(e)?4:j(e)?2:0;return ii(e,t,n,s,r,o,i,!0)}function yl(e){return e?Pr(e)||vn in e?ie({},e):e:null}function qe(e,t,n=!1){const{props:s,ref:r,patchFlag:i,children:o}=e,l=t?vl(s||{},t):s;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&ri(l),ref:t&&t.ref?n&&r?L(r)?r.concat(Jt(t)):[r,Jt(t)]:Jt(t):r,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==he?i===-1?16:i|16:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&qe(e.ssContent),ssFallback:e.ssFallback&&qe(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function oi(e=" ",t=0){return ce(mt,null,e,t)}function Wc(e,t){const n=ce(Rt,null,e);return n.staticCount=t,n}function Vc(e="",t=!1){return t?(ti(),si(be,null,e)):ce(be,null,e)}function Te(e){return e==null||typeof e=="boolean"?ce(be):L(e)?ce(he,null,e.slice()):typeof e=="object"?Ke(e):ce(mt,null,String(e))}function Ke(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:qe(e)}function hs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(L(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),hs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!(vn in t)?t._ctx=ae:r===3&&ae&&(ae.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else j(t)?(t={default:t,_ctx:ae},n=32):(t=String(t),s&64?(n=16,t=[oi(t)]):n=8);e.children=t,e.shapeFlag|=n}function vl(...e){const t={};for(let n=0;noe||ae;let ps,lt,Ks="__VUE_INSTANCE_SETTERS__";(lt=Sn()[Ks])||(lt=Sn()[Ks]=[]),lt.push(e=>oe=e),ps=e=>{lt.length>1?lt.forEach(t=>t(e)):lt[0](e)};const _t=e=>{ps(e),e.scope.on()},st=()=>{oe&&oe.scope.off(),ps(null)};function ci(e){return e.vnode.shapeFlag&4}let Lt=!1;function El(e,t=!1){Lt=t;const{props:n,children:s}=e.vnode,r=ci(e);ll(e,n,r,t),al(e,s);const i=r?Tl(e,t):void 0;return Lt=!1,i}function Tl(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Tt(new Proxy(e.ctx,Zo));const{setup:s}=n;if(s){const r=e.setupContext=s.length>1?ai(e):null;_t(e),bt();const i=We(s,e,0,[e.props,r]);if(yt(),st(),dr(i)){if(i.then(st,st),t)return i.then(o=>{ks(e,o,t)}).catch(o=>{dn(o,e,0)});e.asyncDep=i}else ks(e,i,t)}else fi(e,t)}function ks(e,t,n){j(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ee(t)&&(e.setupState=Or(t)),fi(e,n)}let Ws;function fi(e,t,n){const s=e.type;if(!e.render){if(!t&&Ws&&!s.render){const r=s.template||us(e).template;if(r){const{isCustomElement:i,compilerOptions:o}=e.appContext.config,{delimiters:l,compilerOptions:c}=s,a=ie(ie({isCustomElement:i,delimiters:l},o),c);s.render=Ws(r,a)}}e.render=s.render||Pe}_t(e),bt(),Go(e),yt(),st()}function Al(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return pe(e,"get","$attrs"),t[n]}}))}function ai(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return Al(e)},slots:e.slots,emit:e.emit,expose:t}}function gs(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Or(Tt(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in At)return At[n](e)},has(t,n){return n in t||n in At}}))}function Rl(e,t=!0){return j(e)?e.displayName||e.name:e.name||t&&e.__name}function Pl(e){return j(e)&&"__vccOpts"in e}const Ee=(e,t)=>Co(e,t,Lt);function kn(e,t,n){const s=arguments.length;return s===2?ee(t)&&!L(t)?on(t)?ce(e,null,[t]):ce(e,t):ce(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&on(n)&&(n=[n]),ce(e,t,n))}const Il=Symbol.for("v-scx"),Ol=()=>pt(Il),Fl="3.3.4",Sl="http://www.w3.org/2000/svg",et=typeof document<"u"?document:null,Vs=et&&et.createElement("template"),Ml={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t?et.createElementNS(Sl,e):et.createElement(e,n?{is:n}:void 0);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>et.createTextNode(e),createComment:e=>et.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>et.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{Vs.innerHTML=s?`${e}`:e;const l=Vs.content;if(s){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};function Ll(e,t,n){const s=e._vtc;s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}function Nl(e,t,n){const s=e.style,r=se(n);if(n&&!r){if(t&&!se(t))for(const i in t)n[i]==null&&Wn(s,i,"");for(const i in n)Wn(s,i,n[i])}else{const i=s.display;r?t!==n&&(s.cssText=n):t&&e.removeAttribute("style"),"_vod"in e&&(s.display=i)}}const qs=/\s*!important$/;function Wn(e,t,n){if(L(n))n.forEach(s=>Wn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=Hl(e,t);qs.test(n)?e.setProperty(rt(s),n.replace(qs,""),"important"):e[s]=n}}const zs=["Webkit","Moz","ms"],Rn={};function Hl(e,t){const n=Rn[t];if(n)return n;let s=Me(t);if(s!=="filter"&&s in e)return Rn[t]=s;s=fn(s);for(let r=0;rPn||(kl.then(()=>Pn=0),Pn=Date.now());function Vl(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;we(ql(s,n.value),t,5,[s])};return n.value=e,n.attached=Wl(),n}function ql(e,t){if(L(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Xs=/^on[a-z]/,zl=(e,t,n,s,r=!1,i,o,l,c)=>{t==="class"?Ll(e,s,r):t==="style"?Nl(e,n,s):Nt(t)?qn(t)||Dl(e,t,n,s,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Yl(e,t,s,r))?Ul(e,t,s,i,o,l,c):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),$l(e,t,s,r))};function Yl(e,t,n,s){return s?!!(t==="innerHTML"||t==="textContent"||t in e&&Xs.test(t)&&j(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||Xs.test(t)&&se(n)?!1:t in e}const Be="transition",xt="animation",ui=(e,{slots:t})=>kn(Bo,Jl(e),t);ui.displayName="Transition";const di={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};ui.props=ie({},Ur,di);const Xe=(e,t=[])=>{L(e)?e.forEach(n=>n(...t)):e&&e(...t)},Zs=e=>e?L(e)?e.some(t=>t.length>1):e.length>1:!1;function Jl(e){const t={};for(const P in e)P in di||(t[P]=e[P]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:a=o,appearToClass:d=l,leaveFromClass:p=`${n}-leave-from`,leaveActiveClass:y=`${n}-leave-active`,leaveToClass:A=`${n}-leave-to`}=e,$=Xl(r),O=$&&$[0],D=$&&$[1],{onBeforeEnter:b,onEnter:w,onEnterCancelled:N,onLeave:R,onLeaveCancelled:K,onBeforeAppear:J=b,onAppear:V=w,onAppearCancelled:T=N}=t,B=(P,k,F)=>{Ze(P,k?d:l),Ze(P,k?a:o),F&&F()},U=(P,k)=>{P._isLeaving=!1,Ze(P,p),Ze(P,A),Ze(P,y),k&&k()},Y=P=>(k,F)=>{const ge=P?V:w,X=()=>B(k,P,F);Xe(ge,[k,X]),Qs(()=>{Ze(k,P?c:i),De(k,P?d:l),Zs(ge)||Gs(k,s,O,X)})};return ie(t,{onBeforeEnter(P){Xe(b,[P]),De(P,i),De(P,o)},onBeforeAppear(P){Xe(J,[P]),De(P,c),De(P,a)},onEnter:Y(!1),onAppear:Y(!0),onLeave(P,k){P._isLeaving=!0;const F=()=>U(P,k);De(P,p),Gl(),De(P,y),Qs(()=>{P._isLeaving&&(Ze(P,p),De(P,A),Zs(R)||Gs(P,s,D,F))}),Xe(R,[P,F])},onEnterCancelled(P){B(P,!1),Xe(N,[P])},onAppearCancelled(P){B(P,!0),Xe(T,[P])},onLeaveCancelled(P){U(P),Xe(K,[P])}})}function Xl(e){if(e==null)return null;if(ee(e))return[In(e.enter),In(e.leave)];{const t=In(e);return[t,t]}}function In(e){return Ii(e)}function De(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e._vtc||(e._vtc=new Set)).add(t)}function Ze(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const{_vtc:n}=e;n&&(n.delete(t),n.size||(e._vtc=void 0))}function Qs(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Zl=0;function Gs(e,t,n,s){const r=e._endId=++Zl,i=()=>{r===e._endId&&s()};if(n)return setTimeout(i,n);const{type:o,timeout:l,propCount:c}=Ql(e,t);if(!o)return s();const a=o+"end";let d=0;const p=()=>{e.removeEventListener(a,y),i()},y=A=>{A.target===e&&++d>=c&&p()};setTimeout(()=>{d(n[$]||"").split(", "),r=s(`${Be}Delay`),i=s(`${Be}Duration`),o=er(r,i),l=s(`${xt}Delay`),c=s(`${xt}Duration`),a=er(l,c);let d=null,p=0,y=0;t===Be?o>0&&(d=Be,p=o,y=i.length):t===xt?a>0&&(d=xt,p=a,y=c.length):(p=Math.max(o,a),d=p>0?o>a?Be:xt:null,y=d?d===Be?i.length:c.length:0);const A=d===Be&&/\b(transform|all)(,|$)/.test(s(`${Be}Property`).toString());return{type:d,timeout:p,propCount:y,hasTransform:A}}function er(e,t){for(;e.lengthtr(n)+tr(e[s])))}function tr(e){return Number(e.slice(0,-1).replace(",","."))*1e3}function Gl(){return document.body.offsetHeight}const ec=["ctrl","shift","alt","meta"],tc={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>ec.some(n=>e[`${n}Key`]&&!t.includes(n))},qc=(e,t)=>(n,...s)=>{for(let r=0;rn=>{if(!("key"in n))return;const s=rt(n.key);if(t.some(r=>r===s||nc[r]===s))return e(n)},sc=ie({patchProp:zl},Ml);let On,nr=!1;function rc(){return On=nr?On:hl(sc),nr=!0,On}const Yc=(...e)=>{const t=rc().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=ic(s);if(r)return n(r,!0,r instanceof SVGElement)},t};function ic(e){return se(e)?document.querySelector(e):e}const Jc=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},oc="modulepreload",lc=function(e){return"/ts-oauth2-server/"+e},sr={},Xc=function(t,n,s){if(!n||n.length===0)return t();const r=document.getElementsByTagName("link");return Promise.all(n.map(i=>{if(i=lc(i),i in sr)return;sr[i]=!0;const o=i.endsWith(".css"),l=o?'[rel="stylesheet"]':"";if(!!s)for(let d=r.length-1;d>=0;d--){const p=r[d];if(p.href===i&&(!o||p.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${i}"]${l}`))return;const a=document.createElement("link");if(a.rel=o?"stylesheet":oc,o||(a.as="script",a.crossOrigin=""),a.href=i,document.head.appendChild(a),o)return new Promise((d,p)=>{a.addEventListener("load",d),a.addEventListener("error",()=>p(new Error(`Unable to preload CSS for ${i}`)))})})).then(()=>t())},cc=window.__VP_SITE_DATA__,hi=/^[a-z]+:/i,Zc=/^pathname:\/\//,Qc="vitepress-theme-appearance",pi=/#.*$/,fc=/(index)?\.(md|html)$/,xe=typeof document<"u",gi={relativePath:"",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function ac(e,t,n=!1){if(t===void 0)return!1;if(e=rr(`/${e}`),n)return new RegExp(t).test(e);if(rr(t)!==e)return!1;const s=t.match(pi);return s?(xe?location.hash:"")===s[0]:!0}function rr(e){return decodeURI(e).replace(pi,"").replace(fc,"")}function uc(e){return hi.test(e)}function dc(e,t){var s,r,i,o,l,c,a;const n=Object.keys(e.locales).find(d=>d!=="root"&&!uc(d)&&ac(t,`/${d}/`,!0))||"root";return Object.assign({},e,{localeIndex:n,lang:((s=e.locales[n])==null?void 0:s.lang)??e.lang,dir:((r=e.locales[n])==null?void 0:r.dir)??e.dir,title:((i=e.locales[n])==null?void 0:i.title)??e.title,titleTemplate:((o=e.locales[n])==null?void 0:o.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:_i(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(a=e.locales[n])==null?void 0:a.themeConfig}})}function mi(e,t){const n=t.title||e.title,s=t.titleTemplate??e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const r=hc(e.title,s);return`${n}${r}`}function hc(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function pc(e,t){const[n,s]=t;if(n!=="meta")return!1;const r=Object.entries(s)[0];return r==null?!1:e.some(([i,o])=>i===n&&o[r[0]]===r[1])}function _i(e,t){return[...e.filter(n=>!pc(t,n)),...t]}const gc=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,mc=/^[a-z]:/i;function ir(e){const t=mc.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(gc,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const _c=Symbol(),tt=po(cc);function Gc(e){const t=Ee(()=>dc(tt.value,e.data.relativePath));return{site:t,theme:Ee(()=>t.value.themeConfig),page:Ee(()=>e.data),frontmatter:Ee(()=>e.data.frontmatter),params:Ee(()=>e.data.params),lang:Ee(()=>t.value.lang),dir:Ee(()=>t.value.dir),localeIndex:Ee(()=>t.value.localeIndex||"root"),title:Ee(()=>mi(t.value,e.data)),description:Ee(()=>e.data.description||t.value.description),isDark:ls(!1)}}function ef(){const e=pt(_c);if(!e)throw new Error("vitepress data not properly injected in app");return e}function bc(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function or(e){return hi.test(e)||e.startsWith(".")?e:bc(tt.value.base,e)}function yc(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),xe){const n="/ts-oauth2-server/";t=ir(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let s=__VP_HASH_MAP__[t.toLowerCase()];s||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",s=__VP_HASH_MAP__[t.toLowerCase()]),t=`${n}assets/${t}.${s}.js`}else t=`./${ir(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let Xt=[];function tf(e){Xt.push(e),yn(()=>{Xt=Xt.filter(t=>t!==e)})}const vc=Symbol(),lr="http://a.com",xc=()=>({path:"/",component:null,data:gi});function nf(e,t){const n=un(xc()),s={route:n,go:r};async function r(l=xe?location.href:"/"){var a,d;await((a=s.onBeforeRouteChange)==null?void 0:a.call(s,l));const c=new URL(l,lr);tt.value.cleanUrls||!c.pathname.endsWith("/")&&!c.pathname.endsWith(".html")&&(c.pathname+=".html",l=c.pathname+c.search+c.hash),xe&&l!==location.href&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",l)),await o(l),await((d=s.onAfterRouteChanged)==null?void 0:d.call(s,l))}let i=null;async function o(l,c=0,a=!1){const d=new URL(l,lr),p=i=d.pathname;try{let y=await e(p);if(i===p){i=null;const{default:A,__pageData:$}=y;if(!A)throw new Error(`Invalid route component: ${A}`);n.path=xe?p:or(p),n.component=Tt(A),n.data=Tt($),xe&&Sr(()=>{let O=tt.value.base+$.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!tt.value.cleanUrls&&!O.endsWith("/")&&(O+=".html"),O!==d.pathname&&(d.pathname=O,l=O+d.search+d.hash,history.replaceState(null,"",l)),d.hash&&!c){let D=null;try{D=document.querySelector(decodeURIComponent(d.hash))}catch(b){console.warn(b)}if(D){cr(D,d.hash);return}}window.scrollTo(0,c)})}}catch(y){if(!/fetch/.test(y.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(y),!a)try{const A=await fetch(tt.value.base+"hashmap.json");window.__VP_HASH_MAP__=await A.json(),await o(l,c,!0);return}catch{}i===p&&(i=null,n.path=xe?p:or(p),n.component=t?Tt(t):null,n.data=gi)}}return xe&&(window.addEventListener("click",l=>{if(l.target.closest("button"))return;const a=l.target.closest("a");if(a&&!a.closest(".vp-raw")&&(a instanceof SVGElement||!a.download)){const{target:d}=a,{href:p,origin:y,pathname:A,hash:$,search:O}=new URL(a.href instanceof SVGAnimatedString?a.href.animVal:a.href,a.baseURI),D=window.location,b=A.match(/\.\w+$/);!l.ctrlKey&&!l.shiftKey&&!l.altKey&&!l.metaKey&&d!=="_blank"&&y===D.origin&&!(b&&b[0]!==".html")&&(l.preventDefault(),A===D.pathname&&O===D.search?$&&($!==D.hash&&(history.pushState(null,"",$),window.dispatchEvent(new Event("hashchange"))),cr(a,$,a.classList.contains("header-anchor"))):r(p))}},{capture:!0}),window.addEventListener("popstate",l=>{o(location.href,l.state&&l.state.scrollPosition||0)}),window.addEventListener("hashchange",l=>{l.preventDefault()})),s}function wc(){const e=pt(vc);if(!e)throw new Error("useRouter() is called without provider.");return e}function bi(){return wc().route}function cr(e,t,n=!1){let s=null;try{s=e.classList.contains("header-anchor")?e:document.querySelector(decodeURIComponent(t))}catch(r){console.warn(r)}if(s){const r=tt.value.scrollOffset;let i=0;if(typeof r=="number")i=r;else if(typeof r=="string")i=fr(r);else if(Array.isArray(r))for(const c of r){const a=fr(c);if(a){i=a;break}}const o=parseInt(window.getComputedStyle(s).paddingTop,10),l=window.scrollY+s.getBoundingClientRect().top-i+o;!n||Math.abs(l-window.scrollY)>window.innerHeight?window.scrollTo(0,l):window.scrollTo({left:0,top:l,behavior:"smooth"})}}function fr(e){const t=document.querySelector(e);if(!t)return 0;const n=t.getBoundingClientRect().bottom;return n<0?0:n+24}const ar=()=>Xt.forEach(e=>e()),sf=Dr({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=bi();return()=>kn(e.as,{style:{position:"relative"}},[t.component?kn(t.component,{onVnodeMounted:ar,onVnodeUpdated:ar}):"404 Page Not Found"])}});function rf(e,t){let n=[],s=!0;const r=i=>{if(s){s=!1;return}n.forEach(o=>document.head.removeChild(o)),n=[],i.forEach(o=>{const l=Cc(o);document.head.appendChild(l),n.push(l)})};Ho(()=>{const i=e.data,o=t.value,l=i&&i.description,c=i&&i.frontmatter.head||[];document.title=mi(o,i),document.querySelector("meta[name=description]").setAttribute("content",l||o.description),r(_i(o.head,Tc(c)))})}function Cc([e,t,n]){const s=document.createElement(e);for(const r in t)s.setAttribute(r,t[r]);return n&&(s.innerHTML=n),s}function Ec(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function Tc(e){return e.filter(t=>!Ec(t))}const Fn=new Set,yi=()=>document.createElement("link"),Ac=e=>{const t=yi();t.rel="prefetch",t.href=e,document.head.appendChild(t)},Rc=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let qt;const Pc=xe&&(qt=yi())&&qt.relList&&qt.relList.supports&&qt.relList.supports("prefetch")?Ac:Rc;function of(){if(!xe||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const s=()=>{n&&n.disconnect(),n=new IntersectionObserver(i=>{i.forEach(o=>{if(o.isIntersecting){const l=o.target;n.unobserve(l);const{pathname:c}=l;if(!Fn.has(c)){Fn.add(c);const a=yc(c);Pc(a)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(i=>{const{target:o}=i,{hostname:l,pathname:c}=new URL(i.href instanceof SVGAnimatedString?i.href.animVal:i.href,i.baseURI),a=c.match(/\.\w+$/);a&&a[0]!==".html"||o!=="_blank"&&l===location.hostname&&(c!==location.pathname?n.observe(i):Fn.add(c))})})};bn(s);const r=bi();Yt(()=>r.path,s),yn(()=>{n&&n.disconnect()})}const lf=Dr({setup(e,{slots:t}){const n=ls(!1);return bn(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function cf(){if(xe){const e=new Map;window.addEventListener("click",t=>{var s;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const r=n.parentElement,i=(s=n.nextElementSibling)==null?void 0:s.nextElementSibling;if(!r||!i)return;const o=/language-(shellscript|shell|bash|sh|zsh)/.test(r.className);let l="";i.querySelectorAll("span.line:not(.diff.remove)").forEach(c=>l+=(c.textContent||"")+` +`),l=l.slice(0,-1),o&&(l=l.replace(/^ *(\$|>) /gm,"").trim()),Ic(l).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const c=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,c)})}})}}async function Ic(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const s=document.getSelection(),r=s?s.rangeCount>0&&s.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),r&&(s.removeAllRanges(),s.addRange(r)),n&&n.focus()}}function ff(){xe&&window.addEventListener("click",e=>{var n,s;const t=e.target;if(t.matches(".vp-code-group input")){const r=(n=t.parentElement)==null?void 0:n.parentElement,i=Array.from((r==null?void 0:r.querySelectorAll("input"))||[]).indexOf(t),o=r==null?void 0:r.querySelector('div[class*="language-"].active'),l=(s=r==null?void 0:r.querySelectorAll('div[class*="language-"]:not(.language-id)'))==null?void 0:s[i];o&&l&&o!==l&&(o.classList.remove("active"),l.classList.add("active"))}})}export{Hc as $,si as A,Oo as B,Vc as C,$c as D,vl as E,he as F,ce as G,Xn as H,Uc as I,hi as J,xe as K,jc as L,Lc as M,Nc as N,Wc as O,Zc as P,Qc as Q,pt as R,ol as S,ui as T,qo as U,tf as V,po as W,Sr as X,zc as Y,Dc as Z,Jc as _,oi as a,qc as a0,Kc as a1,rf as a2,vc as a3,Gc as a4,_c as a5,sf as a6,lf as a7,tt as a8,Yc as a9,nf as aa,yc as ab,Xc as ac,of as ad,cf as ae,ff as af,kn as ag,mo as b,kc as c,Dr as d,Mc as e,Rr as f,Sc as g,ls as h,Ui as i,Fc as j,Ho as k,Ee as l,li as m,Zn as n,ti as o,bn as p,uc as q,Bc as r,or as s,Oc as t,ef as u,ac as v,Yt as w,bi as x,yn as y,ii as z}; diff --git a/assets/chunks/theme.d98fd9e6.js b/assets/chunks/theme.d98fd9e6.js new file mode 100644 index 00000000..5acc1685 --- /dev/null +++ b/assets/chunks/theme.d98fd9e6.js @@ -0,0 +1,7 @@ +import{d as g,o as a,c as l,r as c,n as C,a as T,t as P,_ as f,u as Qe,b as i,e as Je,f as xe,g as Ze,h as S,i as et,j as tt,w as q,k as Q,l as $,m as nt,p as F,q as st,P as ot,s as pe,v as K,x as ee,y as he,z as u,F as L,A as y,B as v,T as fe,C as m,D as R,E as se,G as h,H as He,I as U,J as Ee,K as at,L as A,M as H,N as E,O as rt,Q as Ie,R as me,S as oe,U as it,V as J,W as ge,X as lt,Y as ct,Z as ut,$ as dt,a0 as _t,a1 as vt}from"./framework.2958c35d.js";const pt=g({__name:"VPBadge",props:{text:{},type:{}},setup(n){return(e,t)=>(a(),l("span",{class:C(["VPBadge",e.type??"tip"])},[c(e.$slots,"default",{},()=>[T(P(e.text),1)],!0)],2))}});const ht=f(pt,[["__scopeId","data-v-9b69adbb"]]),V=Qe;function ze(n){return et()?(tt(n),!0):!1}function De(n){return typeof n=="function"?n():i(n)}const ft=typeof window<"u",Fe=()=>{};function mt(...n){if(n.length!==1)return Je(...n);const e=n[0];return typeof e=="function"?xe(Ze(()=>({get:e,set:Fe}))):S(e)}function gt(n){var e;const t=De(n);return(e=t==null?void 0:t.$el)!=null?e:t}const ye=ft?window:void 0;function yt(...n){let e,t,o,s;if(typeof n[0]=="string"||Array.isArray(n[0])?([t,o,s]=n,e=ye):[e,t,o,s]=n,!e)return Fe;Array.isArray(t)||(t=[t]),Array.isArray(o)||(o=[o]);const r=[],d=()=>{r.forEach(M=>M()),r.length=0},p=(M,I,w,k)=>(M.addEventListener(I,w,k),()=>M.removeEventListener(I,w,k)),_=q(()=>[gt(e),De(s)],([M,I])=>{d(),M&&r.push(...t.flatMap(w=>o.map(k=>p(M,w,k,I))))},{immediate:!0,flush:"post"}),b=()=>{_(),d()};return ze(b),b}function bt(){const n=S(!1);return nt()&&F(()=>{n.value=!0}),n}function $t(n){const e=bt();return $(()=>(e.value,!!n()))}function de(n,e={}){const{window:t=ye}=e,o=$t(()=>t&&"matchMedia"in t&&typeof t.matchMedia=="function");let s;const r=S(!1),d=()=>{s&&("removeEventListener"in s?s.removeEventListener("change",p):s.removeListener(p))},p=()=>{o.value&&(d(),s=t.matchMedia(mt(n).value),r.value=!!(s!=null&&s.matches),s&&("addEventListener"in s?s.addEventListener("change",p):s.addListener(p)))};return Q(p),ze(()=>d()),r}function kt({window:n=ye}={}){if(!n)return{x:S(0),y:S(0)};const e=S(n.scrollX),t=S(n.scrollY);return yt(n,"scroll",()=>{e.value=n.scrollX,t.value=n.scrollY},{capture:!1,passive:!0}),{x:e,y:t}}function Pt(n,e){let t,o=!1;return()=>{t&&clearTimeout(t),o?t=setTimeout(n,e):(n(),o=!0,setTimeout(()=>{o=!1},e))}}function _e(n){return/^\//.test(n)?n:`/${n}`}function Z(n){if(st(n))return n.replace(ot,"");const{site:e}=V(),{pathname:t,search:o,hash:s}=new URL(n,"http://example.com"),r=t.endsWith("/")||t.endsWith(".html")?n:n.replace(/(?:(^\.+)\/)?.*$/,`$1${t.replace(/(\.md)?$/,e.value.cleanUrls?"":".html")}${o}${s}`);return pe(r)}function Oe(n,e){if(Array.isArray(n))return n;if(n==null)return[];e=_e(e);const t=Object.keys(n).sort((o,s)=>s.split("/").length-o.split("/").length).find(o=>e.startsWith(_e(o)));return t?n[t]:[]}function Vt(n){const e=[];let t=0;for(const o in n){const s=n[o];if(s.items){t=e.push(s);continue}e[t]||e.push({items:[]}),e[t].items.push(s)}return e}function wt(n){const e=[];function t(o){for(const s of o)s.text&&s.link&&e.push({text:s.text,link:s.link}),s.items&&t(s.items)}return t(n),e}function ve(n,e){return Array.isArray(e)?e.some(t=>ve(n,t)):K(n,e.link)?!0:e.items?ve(n,e.items):!1}function z(){const n=ee(),{theme:e,frontmatter:t}=V(),o=de("(min-width: 960px)"),s=S(!1),r=$(()=>{const N=e.value.sidebar,x=n.data.relativePath;return N?Oe(N,x):[]}),d=$(()=>t.value.sidebar!==!1&&r.value.length>0&&t.value.layout!=="home"),p=$(()=>_?t.value.aside==null?e.value.aside==="left":t.value.aside==="left":!1),_=$(()=>t.value.layout==="home"?!1:t.value.aside!=null?!!t.value.aside:e.value.aside!==!1),b=$(()=>d.value&&o.value),M=$(()=>d.value?Vt(r.value):[]);function I(){s.value=!0}function w(){s.value=!1}function k(){s.value?w():I()}return{isOpen:s,sidebar:r,sidebarGroups:M,hasSidebar:d,hasAside:_,leftAside:p,isSidebarEnabled:b,open:I,close:w,toggle:k}}function St(n,e){let t;Q(()=>{t=n.value?document.activeElement:void 0}),F(()=>{window.addEventListener("keyup",o)}),he(()=>{window.removeEventListener("keyup",o)});function o(s){s.key==="Escape"&&n.value&&(e(),t==null||t.focus())}}function Lt(n){const{page:e}=V(),t=S(!1),o=$(()=>n.value.collapsed!=null),s=$(()=>!!n.value.link),r=$(()=>K(e.value.relativePath,n.value.link)),d=$(()=>r.value?!0:n.value.items?ve(e.value.relativePath,n.value.items):!1),p=$(()=>!!(n.value.items&&n.value.items.length));Q(()=>{t.value=!!(o.value&&n.value.collapsed)}),Q(()=>{(r.value||d.value)&&(t.value=!1)});function _(){o.value&&(t.value=!t.value)}return{collapsed:t,collapsible:o,isLink:s,isActiveLink:r,hasActiveLink:d,hasChildren:p,toggle:_}}const Mt=g({__name:"VPSkipLink",setup(n){const e=ee(),t=S();q(()=>e.path,()=>t.value.focus());function o({target:s}){const r=document.querySelector(decodeURIComponent(s.hash));if(r){const d=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",d)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",d),r.focus(),window.scrollTo(0,0)}}return(s,r)=>(a(),l(L,null,[u("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),u("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:o}," Skip to content ")],64))}});const Ct=f(Mt,[["__scopeId","data-v-a9cecaf0"]]),Bt={key:0,class:"VPBackdrop"},It=g({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(n){return(e,t)=>(a(),y(fe,{name:"fade"},{default:v(()=>[e.show?(a(),l("div",Bt)):m("",!0)]),_:1}))}});const Nt=f(It,[["__scopeId","data-v-2b17fbdf"]]);function Tt(){const n=S(!1);function e(){n.value=!0,window.addEventListener("resize",s)}function t(){n.value=!1,window.removeEventListener("resize",s)}function o(){n.value?t():e()}function s(){window.outerWidth>=768&&t()}const r=ee();return q(()=>r.path,t),{isScreenOpen:n,openScreen:e,closeScreen:t,toggleScreen:o}}function te({removeCurrent:n=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:o,page:s,theme:r}=V(),d=$(()=>{var _,b;return{label:(_=t.value.locales[o.value])==null?void 0:_.label,link:((b=t.value.locales[o.value])==null?void 0:b.link)||(o.value==="root"?"/":`/${o.value}/`)}});return{localeLinks:$(()=>Object.entries(t.value.locales).flatMap(([_,b])=>n&&d.value.label===b.label?[]:{text:b.label,link:At(b.link||(_==="root"?"/":`/${_}/`),r.value.i18nRouting!==!1&&e,s.value.relativePath.slice(d.value.link.length-1),!t.value.cleanUrls)})),currentLang:d}}function At(n,e,t,o){return e?n.replace(/\/$/,"")+_e(t.replace(/(^|\/)?index.md$/,"$1").replace(/\.md$/,o?".html":"")):n}const xt=["src","alt"],Ht={inheritAttrs:!1},Et=g({...Ht,__name:"VPImage",props:{image:{},alt:{}},setup(n){return(e,t)=>{const o=R("VPImage",!0);return e.image?(a(),l(L,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),l("img",se({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:i(pe)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,xt)):(a(),l(L,{key:1},[h(o,se({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),h(o,se({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):m("",!0)}}});const be=f(Et,[["__scopeId","data-v-db57fb8d"]]),zt=["href"],Dt=g({__name:"VPNavBarTitle",setup(n){const{site:e,theme:t}=V(),{hasSidebar:o}=z(),{currentLang:s}=te();return(r,d)=>(a(),l("div",{class:C(["VPNavBarTitle",{"has-sidebar":i(o)}])},[u("a",{class:"title",href:i(Z)(i(s).link)},[c(r.$slots,"nav-bar-title-before",{},void 0,!0),i(t).logo?(a(),y(be,{key:0,class:"logo",image:i(t).logo},null,8,["image"])):m("",!0),i(t).siteTitle?(a(),l(L,{key:1},[T(P(i(t).siteTitle),1)],64)):i(t).siteTitle===void 0?(a(),l(L,{key:2},[T(P(i(e).title),1)],64)):m("",!0),c(r.$slots,"nav-bar-title-after",{},void 0,!0)],8,zt)],2))}});const Ft=f(Dt,[["__scopeId","data-v-a11742b6"]]);const Ot={type:"button",class:"DocSearch DocSearch-Button","aria-label":"Search"},Gt={class:"DocSearch-Button-Container"},Rt=u("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[u("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Ut={class:"DocSearch-Button-Placeholder"},jt=u("span",{class:"DocSearch-Button-Keys"},[u("kbd",{class:"DocSearch-Button-Key"}),u("kbd",{class:"DocSearch-Button-Key"},"K")],-1),Ne=g({__name:"VPNavBarSearchButton",props:{placeholder:{}},setup(n){return(e,t)=>(a(),l("button",Ot,[u("span",Gt,[Rt,u("span",Ut,P(e.placeholder),1)]),jt]))}});const qt={id:"local-search"},Kt={key:1,id:"docsearch"},Wt=g({__name:"VPNavBarSearch",setup(n){const e=()=>null,t=()=>null,{theme:o,localeIndex:s}=V(),r=S(!1),d=$(()=>{var k,N,x,B,D,ne,W;const w=((k=o.value.search)==null?void 0:k.options)??o.value.algolia;return((D=(B=(x=(N=w==null?void 0:w.locales)==null?void 0:N[s.value])==null?void 0:x.translations)==null?void 0:B.button)==null?void 0:D.buttonText)||((W=(ne=w==null?void 0:w.translations)==null?void 0:ne.button)==null?void 0:W.buttonText)||"Search"});F(()=>{});function p(){r.value||(r.value=!0,setTimeout(_,16))}function _(){const w=new Event("keydown");w.key="k",w.metaKey=!0,window.dispatchEvent(w),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||_()},16)}const b=S(!1),M=S("'Meta'");F(()=>{M.value=/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?"'⌘'":"'Ctrl'"});const I="";return(w,k)=>{var N;return a(),l("div",{class:"VPNavBarSearch",style:He({"--vp-meta-key":M.value})},[i(I)==="local"?(a(),l(L,{key:0},[b.value?(a(),y(i(e),{key:0,placeholder:d.value,onClose:k[0]||(k[0]=x=>b.value=!1)},null,8,["placeholder"])):m("",!0),u("div",qt,[h(Ne,{placeholder:d.value,onClick:k[1]||(k[1]=x=>b.value=!0)},null,8,["placeholder"])])],64)):i(I)==="algolia"?(a(),l(L,{key:1},[r.value?(a(),y(i(t),{key:0,algolia:((N=i(o).search)==null?void 0:N.options)??i(o).algolia},null,8,["algolia"])):(a(),l("div",Kt,[h(Ne,{placeholder:d.value,onClick:p},null,8,["placeholder"])]))],64)):m("",!0)],4)}}});const Yt={},Xt={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",height:"24px",viewBox:"0 0 24 24",width:"24px"},Qt=u("path",{d:"M0 0h24v24H0V0z",fill:"none"},null,-1),Jt=u("path",{d:"M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z"},null,-1),Zt=[Qt,Jt];function en(n,e){return a(),l("svg",Xt,Zt)}const tn=f(Yt,[["render",en]]),nn=g({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(n){const e=n,t=$(()=>e.tag??e.href?"a":"span"),o=$(()=>e.href&&Ee.test(e.href));return(s,r)=>(a(),y(U(t.value),{class:C(["VPLink",{link:s.href}]),href:s.href?i(Z)(s.href):void 0,target:s.target||(o.value?"_blank":void 0),rel:s.rel||(o.value?"noreferrer":void 0)},{default:v(()=>[c(s.$slots,"default",{},void 0,!0),o.value&&!s.noIcon?(a(),y(tn,{key:0,class:"icon"})):m("",!0)]),_:3},8,["class","href","target","rel"]))}});const O=f(nn,[["__scopeId","data-v-99223c31"]]),sn=g({__name:"VPNavBarMenuLink",props:{item:{}},setup(n){const{page:e}=V();return(t,o)=>(a(),y(O,{class:C({VPNavBarMenuLink:!0,active:i(K)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:v(()=>[T(P(t.item.text),1)]),_:1},8,["class","href","target","rel"]))}});const on=f(sn,[["__scopeId","data-v-60fab7df"]]),$e=S();let Ge=!1,ue=0;function an(n){const e=S(!1);if(at){!Ge&&rn(),ue++;const t=q($e,o=>{var s,r,d;o===n.el.value||(s=n.el.value)!=null&&s.contains(o)?(e.value=!0,(r=n.onFocus)==null||r.call(n)):(e.value=!1,(d=n.onBlur)==null||d.call(n))});he(()=>{t(),ue--,ue||ln()})}return xe(e)}function rn(){document.addEventListener("focusin",Re),Ge=!0,$e.value=document.activeElement}function ln(){document.removeEventListener("focusin",Re)}function Re(){$e.value=document.activeElement}const cn={},un={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},dn=u("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),_n=[dn];function vn(n,e){return a(),l("svg",un,_n)}const Ue=f(cn,[["render",vn]]),pn={},hn={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},fn=u("circle",{cx:"12",cy:"12",r:"2"},null,-1),mn=u("circle",{cx:"19",cy:"12",r:"2"},null,-1),gn=u("circle",{cx:"5",cy:"12",r:"2"},null,-1),yn=[fn,mn,gn];function bn(n,e){return a(),l("svg",hn,yn)}const $n=f(pn,[["render",bn]]),kn={class:"VPMenuLink"},Pn=g({__name:"VPMenuLink",props:{item:{}},setup(n){const{page:e}=V();return(t,o)=>(a(),l("div",kn,[h(O,{class:C({active:i(K)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:v(()=>[T(P(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}});const le=f(Pn,[["__scopeId","data-v-c494398b"]]),Vn={class:"VPMenuGroup"},wn={key:0,class:"title"},Sn=g({__name:"VPMenuGroup",props:{text:{},items:{}},setup(n){return(e,t)=>(a(),l("div",Vn,[e.text?(a(),l("p",wn,P(e.text),1)):m("",!0),(a(!0),l(L,null,A(e.items,o=>(a(),l(L,null,["link"in o?(a(),y(le,{key:0,item:o},null,8,["item"])):m("",!0)],64))),256))]))}});const Ln=f(Sn,[["__scopeId","data-v-b86dd50d"]]),Mn={class:"VPMenu"},Cn={key:0,class:"items"},Bn=g({__name:"VPMenu",props:{items:{}},setup(n){return(e,t)=>(a(),l("div",Mn,[e.items?(a(),l("div",Cn,[(a(!0),l(L,null,A(e.items,o=>(a(),l(L,{key:o.text},["link"in o?(a(),y(le,{key:0,item:o},null,8,["item"])):(a(),y(Ln,{key:1,text:o.text,items:o.items},null,8,["text","items"]))],64))),128))])):m("",!0),c(e.$slots,"default",{},void 0,!0)]))}});const In=f(Bn,[["__scopeId","data-v-eba8cec3"]]),Nn=["aria-expanded","aria-label"],Tn={key:0,class:"text"},An={class:"menu"},xn=g({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(n){const e=S(!1),t=S();an({el:t,onBlur:o});function o(){e.value=!1}return(s,r)=>(a(),l("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=d=>e.value=!0),onMouseleave:r[2]||(r[2]=d=>e.value=!1)},[u("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":s.label,onClick:r[0]||(r[0]=d=>e.value=!e.value)},[s.button||s.icon?(a(),l("span",Tn,[s.icon?(a(),y(U(s.icon),{key:0,class:"option-icon"})):m("",!0),T(" "+P(s.button)+" ",1),h(Ue,{class:"text-icon"})])):(a(),y($n,{key:1,class:"icon"}))],8,Nn),u("div",An,[h(In,{items:s.items},{default:v(()=>[c(s.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}});const ke=f(xn,[["__scopeId","data-v-eba080dd"]]),Hn=g({__name:"VPNavBarMenuGroup",props:{item:{}},setup(n){const{page:e}=V();return(t,o)=>(a(),y(ke,{class:C({VPNavBarMenuGroup:!0,active:i(K)(i(e).relativePath,t.item.activeMatch,!!t.item.activeMatch)}),button:t.item.text,items:t.item.items},null,8,["class","button","items"]))}}),En=n=>(H("data-v-1f756838"),n=n(),E(),n),zn={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},Dn=En(()=>u("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Fn=g({__name:"VPNavBarMenu",setup(n){const{theme:e}=V();return(t,o)=>i(e).nav?(a(),l("nav",zn,[Dn,(a(!0),l(L,null,A(i(e).nav,s=>(a(),l(L,{key:s.text},["link"in s?(a(),y(on,{key:0,item:s},null,8,["item"])):(a(),y(Hn,{key:1,item:s},null,8,["item"]))],64))),128))])):m("",!0)}});const On=f(Fn,[["__scopeId","data-v-1f756838"]]),Gn={},Rn={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Un=u("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),jn=u("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),qn=[Un,jn];function Kn(n,e){return a(),l("svg",Rn,qn)}const je=f(Gn,[["render",Kn]]),Wn={class:"items"},Yn={class:"title"},Xn=g({__name:"VPNavBarTranslations",setup(n){const{theme:e}=V(),{localeLinks:t,currentLang:o}=te({correspondingLink:!0});return(s,r)=>i(t).length&&i(o).label?(a(),y(ke,{key:0,class:"VPNavBarTranslations",icon:je,label:i(e).langMenuLabel||"Change language"},{default:v(()=>[u("div",Wn,[u("p",Yn,P(i(o).label),1),(a(!0),l(L,null,A(i(t),d=>(a(),y(le,{key:d.link,item:d},null,8,["item"]))),128))])]),_:1},8,["label"])):m("",!0)}});const Qn=f(Xn,[["__scopeId","data-v-a02f8de7"]]);const Jn={},Zn={class:"VPSwitch",type:"button",role:"switch"},es={class:"check"},ts={key:0,class:"icon"};function ns(n,e){return a(),l("button",Zn,[u("span",es,[n.$slots.default?(a(),l("span",ts,[c(n.$slots,"default",{},void 0,!0)])):m("",!0)])])}const ss=f(Jn,[["render",ns],["__scopeId","data-v-863a2c7f"]]),os={},as={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},rs=rt('',9),is=[rs];function ls(n,e){return a(),l("svg",as,is)}const cs=f(os,[["render",ls]]),us={},ds={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},_s=u("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),vs=[_s];function ps(n,e){return a(),l("svg",ds,vs)}const hs=f(us,[["render",ps]]),fs=g({__name:"VPSwitchAppearance",setup(n){const{site:e,isDark:t}=V(),o=S(!1),s=typeof localStorage<"u"?r():()=>{};F(()=>{o.value=document.documentElement.classList.contains("dark")});function r(){const d=window.matchMedia("(prefers-color-scheme: dark)"),p=document.documentElement.classList;let _=localStorage.getItem(Ie),b=e.value.appearance==="dark"&&_==null||(_==="auto"||_==null?d.matches:_==="dark");d.onchange=w=>{_==="auto"&&I(b=w.matches)};function M(){I(b=!b),_=b?d.matches?"auto":"dark":d.matches?"light":"auto",localStorage.setItem(Ie,_)}function I(w){const k=document.createElement("style");k.type="text/css",k.appendChild(document.createTextNode(`:not(.VPSwitchAppearance):not(.VPSwitchAppearance *) { + -webkit-transition: none !important; + -moz-transition: none !important; + -o-transition: none !important; + -ms-transition: none !important; + transition: none !important; +}`)),document.head.appendChild(k),o.value=w,p[w?"add":"remove"]("dark"),window.getComputedStyle(k).opacity,document.head.removeChild(k)}return M}return q(o,d=>{t.value=d}),(d,p)=>(a(),y(ss,{title:"toggle dark mode",class:"VPSwitchAppearance","aria-checked":o.value,onClick:i(s)},{default:v(()=>[h(cs,{class:"sun"}),h(hs,{class:"moon"})]),_:1},8,["aria-checked","onClick"]))}});const Pe=f(fs,[["__scopeId","data-v-0f4f1edf"]]),ms={key:0,class:"VPNavBarAppearance"},gs=g({__name:"VPNavBarAppearance",setup(n){const{site:e}=V();return(t,o)=>i(e).appearance?(a(),l("div",ms,[h(Pe)])):m("",!0)}});const ys=f(gs,[["__scopeId","data-v-8a490153"]]),bs={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',slack:'Slack',twitter:'Twitter',youtube:'YouTube'},$s=["href","aria-label","innerHTML"],ks=g({__name:"VPSocialLink",props:{icon:{},link:{}},setup(n){const e=n,t=$(()=>typeof e.icon=="object"?e.icon.svg:bs[e.icon]);return(o,s)=>(a(),l("a",{class:"VPSocialLink",href:o.link,"aria-label":typeof o.icon=="string"?o.icon:"",target:"_blank",rel:"noopener",innerHTML:t.value},null,8,$s))}});const Ps=f(ks,[["__scopeId","data-v-363a4685"]]),Vs={class:"VPSocialLinks"},ws=g({__name:"VPSocialLinks",props:{links:{}},setup(n){return(e,t)=>(a(),l("div",Vs,[(a(!0),l(L,null,A(e.links,({link:o,icon:s})=>(a(),y(Ps,{key:o,icon:s,link:o},null,8,["icon","link"]))),128))]))}});const Ve=f(ws,[["__scopeId","data-v-2fb8166f"]]),Ss=g({__name:"VPNavBarSocialLinks",setup(n){const{theme:e}=V();return(t,o)=>i(e).socialLinks?(a(),y(Ve,{key:0,class:"VPNavBarSocialLinks",links:i(e).socialLinks},null,8,["links"])):m("",!0)}});const Ls=f(Ss,[["__scopeId","data-v-ac78dc9e"]]),Ms={key:0,class:"group translations"},Cs={class:"trans-title"},Bs={key:1,class:"group"},Is={class:"item appearance"},Ns={class:"label"},Ts={class:"appearance-action"},As={key:2,class:"group"},xs={class:"item social-links"},Hs=g({__name:"VPNavBarExtra",setup(n){const{site:e,theme:t}=V(),{localeLinks:o,currentLang:s}=te({correspondingLink:!0}),r=$(()=>o.value.length&&s.value.label||e.value.appearance||t.value.socialLinks);return(d,p)=>r.value?(a(),y(ke,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:v(()=>[i(o).length&&i(s).label?(a(),l("div",Ms,[u("p",Cs,P(i(s).label),1),(a(!0),l(L,null,A(i(o),_=>(a(),y(le,{key:_.link,item:_},null,8,["item"]))),128))])):m("",!0),i(e).appearance?(a(),l("div",Bs,[u("div",Is,[u("p",Ns,P(i(t).darkModeSwitchLabel||"Appearance"),1),u("div",Ts,[h(Pe)])])])):m("",!0),i(t).socialLinks?(a(),l("div",As,[u("div",xs,[h(Ve,{class:"social-links-list",links:i(t).socialLinks},null,8,["links"])])])):m("",!0)]),_:1})):m("",!0)}});const Es=f(Hs,[["__scopeId","data-v-4fdc941c"]]),zs=n=>(H("data-v-519742d4"),n=n(),E(),n),Ds=["aria-expanded"],Fs=zs(()=>u("span",{class:"container"},[u("span",{class:"top"}),u("span",{class:"middle"}),u("span",{class:"bottom"})],-1)),Os=[Fs],Gs=g({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(n){return(e,t)=>(a(),l("button",{type:"button",class:C(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=o=>e.$emit("click"))},Os,10,Ds))}});const Rs=f(Gs,[["__scopeId","data-v-519742d4"]]),Us=n=>(H("data-v-e223f26c"),n=n(),E(),n),js={class:"container"},qs={class:"title"},Ks={class:"content"},Ws=Us(()=>u("div",{class:"curtain"},null,-1)),Ys={class:"content-body"},Xs=g({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(n){const{y:e}=kt(),{hasSidebar:t}=z(),o=$(()=>({"has-sidebar":t.value,fill:e.value>0}));return(s,r)=>(a(),l("div",{class:C(["VPNavBar",o.value])},[u("div",js,[u("div",qs,[h(Ft,null,{"nav-bar-title-before":v(()=>[c(s.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(s.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),u("div",Ks,[Ws,u("div",Ys,[c(s.$slots,"nav-bar-content-before",{},void 0,!0),h(Wt,{class:"search"}),h(On,{class:"menu"}),h(Qn,{class:"translations"}),h(ys,{class:"appearance"}),h(Ls,{class:"social-links"}),h(Es,{class:"extra"}),c(s.$slots,"nav-bar-content-after",{},void 0,!0),h(Rs,{class:"hamburger",active:s.isScreenOpen,onClick:r[0]||(r[0]=d=>s.$emit("toggle-screen"))},null,8,["active"])])])])],2))}});const Qs=f(Xs,[["__scopeId","data-v-e223f26c"]]);function Js(n){if(Array.isArray(n)){for(var e=0,t=Array(n.length);e1),j=[],re=!1,Se=-1,Y=void 0,G=void 0,X=void 0,qe=function(e){return j.some(function(t){return!!(t.options.allowTouchMove&&t.options.allowTouchMove(e))})},ie=function(e){var t=e||window.event;return qe(t.target)||t.touches.length>1?!0:(t.preventDefault&&t.preventDefault(),!1)},Zs=function(e){if(X===void 0){var t=!!e&&e.reserveScrollBarGap===!0,o=window.innerWidth-document.documentElement.clientWidth;if(t&&o>0){var s=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);X=document.body.style.paddingRight,document.body.style.paddingRight=s+o+"px"}}Y===void 0&&(Y=document.body.style.overflow,document.body.style.overflow="hidden")},eo=function(){X!==void 0&&(document.body.style.paddingRight=X,X=void 0),Y!==void 0&&(document.body.style.overflow=Y,Y=void 0)},to=function(){return window.requestAnimationFrame(function(){if(G===void 0){G={position:document.body.style.position,top:document.body.style.top,left:document.body.style.left};var e=window,t=e.scrollY,o=e.scrollX,s=e.innerHeight;document.body.style.position="fixed",document.body.style.top=-t,document.body.style.left=-o,setTimeout(function(){return window.requestAnimationFrame(function(){var r=s-window.innerHeight;r&&t>=s&&(document.body.style.top=-(t+r))})},300)}})},no=function(){if(G!==void 0){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=G.position,document.body.style.top=G.top,document.body.style.left=G.left,window.scrollTo(t,e),G=void 0}},so=function(e){return e?e.scrollHeight-e.scrollTop<=e.clientHeight:!1},oo=function(e,t){var o=e.targetTouches[0].clientY-Se;return qe(e.target)?!1:t&&t.scrollTop===0&&o>0||so(t)&&o<0?ie(e):(e.stopPropagation(),!0)},Ke=function(e,t){if(!e){console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");return}if(!j.some(function(s){return s.targetElement===e})){var o={targetElement:e,options:t||{}};j=[].concat(Js(j),[o]),ae?to():Zs(t),ae&&(e.ontouchstart=function(s){s.targetTouches.length===1&&(Se=s.targetTouches[0].clientY)},e.ontouchmove=function(s){s.targetTouches.length===1&&oo(s,e)},re||(document.addEventListener("touchmove",ie,we?{passive:!1}:void 0),re=!0))}},We=function(){ae&&(j.forEach(function(e){e.targetElement.ontouchstart=null,e.targetElement.ontouchmove=null}),re&&(document.removeEventListener("touchmove",ie,we?{passive:!1}:void 0),re=!1),Se=-1),ae?no():eo(),j=[]};const ao=g({__name:"VPNavScreenMenuLink",props:{item:{}},setup(n){const e=me("close-screen");return(t,o)=>(a(),y(O,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:v(()=>[T(P(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const ro=f(ao,[["__scopeId","data-v-aa70a253"]]),io={},lo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},co=u("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),uo=[co];function _o(n,e){return a(),l("svg",lo,uo)}const vo=f(io,[["render",_o]]),po=g({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(n){const e=me("close-screen");return(t,o)=>(a(),y(O,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:v(()=>[T(P(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const Ye=f(po,[["__scopeId","data-v-f77b192e"]]),ho={class:"VPNavScreenMenuGroupSection"},fo={key:0,class:"title"},mo=g({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(n){return(e,t)=>(a(),l("div",ho,[e.text?(a(),l("p",fo,P(e.text),1)):m("",!0),(a(!0),l(L,null,A(e.items,o=>(a(),y(Ye,{key:o.text,item:o},null,8,["item"]))),128))]))}});const go=f(mo,[["__scopeId","data-v-4975e1ab"]]),yo=["aria-controls","aria-expanded"],bo={class:"button-text"},$o=["id"],ko={key:1,class:"group"},Po=g({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(n){const e=n,t=S(!1),o=$(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function s(){t.value=!t.value}return(r,d)=>(a(),l("div",{class:C(["VPNavScreenMenuGroup",{open:t.value}])},[u("button",{class:"button","aria-controls":o.value,"aria-expanded":t.value,onClick:s},[u("span",bo,P(r.text),1),h(vo,{class:"button-icon"})],8,yo),u("div",{id:o.value,class:"items"},[(a(!0),l(L,null,A(r.items,p=>(a(),l(L,{key:p.text},["link"in p?(a(),l("div",{key:p.text,class:"item"},[h(Ye,{item:p},null,8,["item"])])):(a(),l("div",ko,[h(go,{text:p.text,items:p.items},null,8,["text","items"])]))],64))),128))],8,$o)],2))}});const Vo=f(Po,[["__scopeId","data-v-fc451118"]]),wo={key:0,class:"VPNavScreenMenu"},So=g({__name:"VPNavScreenMenu",setup(n){const{theme:e}=V();return(t,o)=>i(e).nav?(a(),l("nav",wo,[(a(!0),l(L,null,A(i(e).nav,s=>(a(),l(L,{key:s.text},["link"in s?(a(),y(ro,{key:0,item:s},null,8,["item"])):(a(),y(Vo,{key:1,text:s.text||"",items:s.items},null,8,["text","items"]))],64))),128))])):m("",!0)}}),Lo={key:0,class:"VPNavScreenAppearance"},Mo={class:"text"},Co=g({__name:"VPNavScreenAppearance",setup(n){const{site:e,theme:t}=V();return(o,s)=>i(e).appearance?(a(),l("div",Lo,[u("p",Mo,P(i(t).darkModeSwitchLabel||"Appearance"),1),h(Pe)])):m("",!0)}});const Bo=f(Co,[["__scopeId","data-v-089a640c"]]),Io={class:"list"},No=g({__name:"VPNavScreenTranslations",setup(n){const{localeLinks:e,currentLang:t}=te({correspondingLink:!0}),o=S(!1);function s(){o.value=!o.value}return(r,d)=>i(e).length&&i(t).label?(a(),l("div",{key:0,class:C(["VPNavScreenTranslations",{open:o.value}])},[u("button",{class:"title",onClick:s},[h(je,{class:"icon lang"}),T(" "+P(i(t).label)+" ",1),h(Ue,{class:"icon chevron"})]),u("ul",Io,[(a(!0),l(L,null,A(i(e),p=>(a(),l("li",{key:p.link,class:"item"},[h(O,{class:"link",href:p.link},{default:v(()=>[T(P(p.text),1)]),_:2},1032,["href"])]))),128))])],2)):m("",!0)}});const To=f(No,[["__scopeId","data-v-35099923"]]),Ao=g({__name:"VPNavScreenSocialLinks",setup(n){const{theme:e}=V();return(t,o)=>i(e).socialLinks?(a(),y(Ve,{key:0,class:"VPNavScreenSocialLinks",links:i(e).socialLinks},null,8,["links"])):m("",!0)}}),xo={class:"container"},Ho=g({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(n){const e=S(null);function t(){Ke(e.value,{reserveScrollBarGap:!0})}function o(){We()}return(s,r)=>(a(),y(fe,{name:"fade",onEnter:t,onAfterLeave:o},{default:v(()=>[s.open?(a(),l("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e},[u("div",xo,[c(s.$slots,"nav-screen-content-before",{},void 0,!0),h(So,{class:"menu"}),h(To,{class:"translations"}),h(Bo,{class:"appearance"}),h(Ao,{class:"social-links"}),c(s.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):m("",!0)]),_:3}))}});const Eo=f(Ho,[["__scopeId","data-v-7f135a4c"]]),zo={class:"VPNav"},Do=g({__name:"VPNav",setup(n){const{isScreenOpen:e,closeScreen:t,toggleScreen:o}=Tt();return oe("close-screen",t),(s,r)=>(a(),l("header",zo,[h(Qs,{"is-screen-open":i(e),onToggleScreen:i(o)},{"nav-bar-title-before":v(()=>[c(s.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(s.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[c(s.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[c(s.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),h(Eo,{open:i(e)},{"nav-screen-content-before":v(()=>[c(s.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[c(s.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])]))}});const Fo=f(Do,[["__scopeId","data-v-9f003a64"]]),Oo={},Go={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Ro=u("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Uo=u("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),jo=u("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),qo=u("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Ko=[Ro,Uo,jo,qo];function Wo(n,e){return a(),l("svg",Go,Ko)}const Yo=f(Oo,[["render",Wo]]);function Xo(){const{hasSidebar:n}=z(),e=de("(min-width: 960px)"),t=de("(min-width: 1280px)");return{isAsideEnabled:$(()=>!t.value&&!e.value?!1:n.value?t.value:e.value)}}const Qo=71;function Le(n){return typeof n.outline=="object"&&!Array.isArray(n.outline)&&n.outline.label||n.outlineTitle||"On this page"}function Me(n){const e=[...document.querySelectorAll(".VPDoc h2,h3,h4,h5,h6")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const o=Number(t.tagName[1]);return{title:Jo(t),link:"#"+t.id,level:o}});return Zo(e,n)}function Jo(n){let e="";for(const t of n.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function Zo(n,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[o,s]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;n=n.filter(d=>d.level>=o&&d.level<=s);const r=[];e:for(let d=0;d=0;_--){const b=n[_];if(b.level{requestAnimationFrame(r),window.addEventListener("scroll",o)}),it(()=>{d(location.hash)}),he(()=>{window.removeEventListener("scroll",o)});function r(){if(!t.value)return;const p=[].slice.call(n.value.querySelectorAll(".outline-link")),_=[].slice.call(document.querySelectorAll(".content .header-anchor")).filter(k=>p.some(N=>N.hash===k.hash&&k.offsetParent!==null)),b=window.scrollY,M=window.innerHeight,I=document.body.offsetHeight,w=Math.abs(b+M-I)<1;if(_.length&&w){d(_[_.length-1].hash);return}for(let k=0;k<_.length;k++){const N=_[k],x=_[k+1],[B,D]=ta(k,N,x);if(B){d(D);return}}}function d(p){s&&s.classList.remove("active"),p!==null&&(s=n.value.querySelector(`a[href="${decodeURIComponent(p)}"]`));const _=s;_?(_.classList.add("active"),e.value.style.top=_.offsetTop+33+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function Ae(n){return n.parentElement.offsetTop-Qo}function ta(n,e,t){const o=window.scrollY;return n===0&&o===0?[!0,null]:o{const s=R("VPDocOutlineItem",!0);return a(),l("ul",{class:C(t.root?"root":"nested")},[(a(!0),l(L,null,A(t.headers,({children:r,link:d,title:p})=>(a(),l("li",null,[u("a",{class:"outline-link",href:d,onClick:e,title:p},P(p),9,na),r!=null&&r.length?(a(),y(s,{key:0,headers:r},null,8,["headers"])):m("",!0)]))),256))],2)}}});const Ce=f(sa,[["__scopeId","data-v-f461fd14"]]),oa={},aa={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ra=u("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),ia=[ra];function la(n,e){return a(),l("svg",aa,ia)}const Be=f(oa,[["render",la]]),ca=g({__name:"VPLocalNavOutlineDropdown",setup(n){const{frontmatter:e,theme:t}=V(),o=S(!1),s=S(0),r=S();J(()=>{o.value=!1});function d(){o.value=!o.value,s.value=window.innerHeight+Math.min(window.scrollY-64,0)}function p(M){M.target.classList.contains("outline-link")&&(r.value&&(r.value.style.transition="none"),lt(()=>{o.value=!1}))}function _(){o.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}const b=ge([]);return J(()=>{b.value=Me(e.value.outline??t.value.outline)}),(M,I)=>(a(),l("div",{class:"VPLocalNavOutlineDropdown",style:He({"--vp-vh":s.value+"px"})},[b.value.length>0?(a(),l("button",{key:0,onClick:d,class:C({open:o.value})},[T(P(i(Le)(i(t)))+" ",1),h(Be,{class:"icon"})],2)):(a(),l("button",{key:1,onClick:_},P(i(t).returnToTopLabel||"Return to top"),1)),h(fe,{name:"flyout"},{default:v(()=>[o.value?(a(),l("div",{key:0,ref_key:"items",ref:r,class:"items",onClick:p},[u("a",{class:"top-link",href:"#",onClick:_},P(i(t).returnToTopLabel||"Return to top"),1),h(Ce,{headers:b.value},null,8,["headers"])],512)):m("",!0)]),_:1})],4))}});const ua=f(ca,[["__scopeId","data-v-57c1b8b6"]]),da={key:0,class:"VPLocalNav"},_a=["aria-expanded"],va={class:"menu-text"},pa=g({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(n){const{theme:e,frontmatter:t}=V(),{hasSidebar:o}=z();return(s,r)=>i(t).layout!=="home"?(a(),l("div",da,[i(o)?(a(),l("button",{key:0,class:"menu","aria-expanded":s.open,"aria-controls":"VPSidebarNav",onClick:r[0]||(r[0]=d=>s.$emit("open-menu"))},[h(Yo,{class:"menu-icon"}),u("span",va,P(i(e).sidebarMenuLabel||"Menu"),1)],8,_a)):m("",!0),h(ua)])):m("",!0)}});const ha=f(pa,[["__scopeId","data-v-8aa06a5b"]]),fa=n=>(H("data-v-7790c0ef"),n=n(),E(),n),ma=["role","tabindex"],ga=fa(()=>u("div",{class:"indicator"},null,-1)),ya=["onKeydown"],ba={key:1,class:"items"},$a=g({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(n){const e=n,{collapsed:t,collapsible:o,isLink:s,isActiveLink:r,hasActiveLink:d,hasChildren:p,toggle:_}=Lt($(()=>e.item)),b=$(()=>p.value?"section":"div"),M=$(()=>s.value?"a":"div"),I=$(()=>p.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),w=$(()=>s.value?void 0:"button"),k=$(()=>[[`level-${e.depth}`],{collapsible:o.value},{collapsed:t.value},{"is-link":s.value},{"is-active":r.value},{"has-active":d.value}]);function N(B){"key"in B&&B.key!=="Enter"||!e.item.link&&_()}function x(){e.item.link&&_()}return(B,D)=>{const ne=R("VPSidebarItem",!0);return a(),y(U(b.value),{class:C(["VPSidebarItem",k.value])},{default:v(()=>[B.item.text?(a(),l("div",se({key:0,class:"item",role:w.value},ut(B.item.items?{click:N,keydown:N}:{},!0),{tabindex:B.item.items&&0}),[ga,B.item.link?(a(),y(O,{key:0,tag:M.value,class:"link",href:B.item.link},{default:v(()=>[(a(),y(U(I.value),{class:"text",innerHTML:B.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href"])):(a(),y(U(I.value),{key:1,class:"text",innerHTML:B.item.text},null,8,["innerHTML"])),B.item.collapsed!=null?(a(),l("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:x,onKeydown:ct(x,["enter"]),tabindex:"0"},[h(Be,{class:"caret-icon"})],40,ya)):m("",!0)],16,ma)):m("",!0),B.item.items&&B.item.items.length?(a(),l("div",ba,[B.depth<5?(a(!0),l(L,{key:0},A(B.item.items,W=>(a(),y(ne,{key:W.text,item:W,depth:B.depth+1},null,8,["item","depth"]))),128)):m("",!0)])):m("",!0)]),_:1},8,["class"])}}});const ka=f($a,[["__scopeId","data-v-7790c0ef"]]),Xe=n=>(H("data-v-36542528"),n=n(),E(),n),Pa=Xe(()=>u("div",{class:"curtain"},null,-1)),Va={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},wa=Xe(()=>u("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),Sa=g({__name:"VPSidebar",props:{open:{type:Boolean}},setup(n){const e=n,{sidebarGroups:t,hasSidebar:o}=z();let s=S(null);function r(){Ke(s.value,{reserveScrollBarGap:!0})}function d(){We()}return dt(async()=>{var p;e.open?(r(),(p=s.value)==null||p.focus()):d()}),(p,_)=>i(o)?(a(),l("aside",{key:0,class:C(["VPSidebar",{open:p.open}]),ref_key:"navEl",ref:s,onClick:_[0]||(_[0]=_t(()=>{},["stop"]))},[Pa,u("nav",Va,[wa,c(p.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),l(L,null,A(i(t),b=>(a(),l("div",{key:b.text,class:"group"},[h(ka,{item:b,depth:0},null,8,["item"])]))),128)),c(p.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):m("",!0)}});const La=f(Sa,[["__scopeId","data-v-36542528"]]),Ma={},Ca={class:"VPPage"};function Ba(n,e){const t=R("Content");return a(),l("div",Ca,[c(n.$slots,"page-top"),h(t),c(n.$slots,"page-bottom")])}const Ia=f(Ma,[["render",Ba]]),Na=g({__name:"VPButton",props:{tag:{},size:{},theme:{},text:{},href:{}},setup(n){const e=n,t=$(()=>[e.size??"medium",e.theme??"brand"]),o=$(()=>e.href&&Ee.test(e.href)),s=$(()=>e.tag?e.tag:e.href?"a":"button");return(r,d)=>(a(),y(U(s.value),{class:C(["VPButton",t.value]),href:r.href?i(Z)(r.href):void 0,target:o.value?"_blank":void 0,rel:o.value?"noreferrer":void 0},{default:v(()=>[T(P(r.text),1)]),_:1},8,["class","href","target","rel"]))}});const Ta=f(Na,[["__scopeId","data-v-49324e83"]]),Aa=n=>(H("data-v-9f53e527"),n=n(),E(),n),xa={class:"container"},Ha={class:"main"},Ea={key:0,class:"name"},za={class:"clip"},Da={key:1,class:"text"},Fa={key:2,class:"tagline"},Oa={key:0,class:"actions"},Ga={key:0,class:"image"},Ra={class:"image-container"},Ua=Aa(()=>u("div",{class:"image-bg"},null,-1)),ja=g({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(n){const e=me("hero-image-slot-exists");return(t,o)=>(a(),l("div",{class:C(["VPHero",{"has-image":t.image||i(e)}])},[u("div",xa,[u("div",Ha,[c(t.$slots,"home-hero-info",{},()=>[t.name?(a(),l("h1",Ea,[u("span",za,P(t.name),1)])):m("",!0),t.text?(a(),l("p",Da,P(t.text),1)):m("",!0),t.tagline?(a(),l("p",Fa,P(t.tagline),1)):m("",!0)],!0),t.actions?(a(),l("div",Oa,[(a(!0),l(L,null,A(t.actions,s=>(a(),l("div",{key:s.link,class:"action"},[h(Ta,{tag:"a",size:"medium",theme:s.theme,text:s.text,href:s.link},null,8,["theme","text","href"])]))),128))])):m("",!0)]),t.image||i(e)?(a(),l("div",Ga,[u("div",Ra,[Ua,c(t.$slots,"home-hero-image",{},()=>[t.image?(a(),y(be,{key:0,class:"image-src",image:t.image},null,8,["image"])):m("",!0)],!0)])])):m("",!0)])],2))}});const qa=f(ja,[["__scopeId","data-v-9f53e527"]]),Ka=g({__name:"VPHomeHero",setup(n){const{frontmatter:e}=V();return(t,o)=>i(e).hero?(a(),y(qa,{key:0,class:"VPHomeHero",name:i(e).hero.name,text:i(e).hero.text,tagline:i(e).hero.tagline,image:i(e).hero.image,actions:i(e).hero.actions},{"home-hero-info":v(()=>[c(t.$slots,"home-hero-info")]),"home-hero-image":v(()=>[c(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):m("",!0)}}),Wa={},Ya={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Xa=u("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),Qa=[Xa];function Ja(n,e){return a(),l("svg",Ya,Qa)}const Za=f(Wa,[["render",Ja]]),er={class:"box"},tr=["innerHTML"],nr=["innerHTML"],sr=["innerHTML"],or={key:3,class:"link-text"},ar={class:"link-text-value"},rr=g({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{}},setup(n){return(e,t)=>(a(),y(O,{class:"VPFeature",href:e.link,"no-icon":!0},{default:v(()=>[u("article",er,[typeof e.icon=="object"?(a(),y(be,{key:0,image:e.icon,alt:e.icon.alt,height:e.icon.height,width:e.icon.width},null,8,["image","alt","height","width"])):e.icon?(a(),l("div",{key:1,class:"icon",innerHTML:e.icon},null,8,tr)):m("",!0),u("h2",{class:"title",innerHTML:e.title},null,8,nr),e.details?(a(),l("p",{key:2,class:"details",innerHTML:e.details},null,8,sr)):m("",!0),e.linkText?(a(),l("div",or,[u("p",ar,[T(P(e.linkText)+" ",1),h(Za,{class:"link-text-icon"})])])):m("",!0)])]),_:1},8,["href"]))}});const ir=f(rr,[["__scopeId","data-v-de84e358"]]),lr={key:0,class:"VPFeatures"},cr={class:"container"},ur={class:"items"},dr=g({__name:"VPFeatures",props:{features:{}},setup(n){const e=n,t=$(()=>{const o=e.features.length;if(o){if(o===2)return"grid-2";if(o===3)return"grid-3";if(o%3===0)return"grid-6";if(o>3)return"grid-4"}else return});return(o,s)=>o.features?(a(),l("div",lr,[u("div",cr,[u("div",ur,[(a(!0),l(L,null,A(o.features,r=>(a(),l("div",{key:r.title,class:C(["item",[t.value]])},[h(ir,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText},null,8,["icon","title","details","link","link-text"])],2))),128))])])])):m("",!0)}});const _r=f(dr,[["__scopeId","data-v-b8390164"]]),vr=g({__name:"VPHomeFeatures",setup(n){const{frontmatter:e}=V();return(t,o)=>i(e).features?(a(),y(_r,{key:0,class:"VPHomeFeatures",features:i(e).features},null,8,["features"])):m("",!0)}}),pr={class:"VPHome"},hr=g({__name:"VPHome",setup(n){return(e,t)=>{const o=R("Content");return a(),l("div",pr,[c(e.$slots,"home-hero-before",{},void 0,!0),h(Ka,null,{"home-hero-info":v(()=>[c(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[c(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),c(e.$slots,"home-hero-after",{},void 0,!0),c(e.$slots,"home-features-before",{},void 0,!0),h(vr),c(e.$slots,"home-features-after",{},void 0,!0),h(o)])}}});const fr=f(hr,[["__scopeId","data-v-dfb75c6d"]]),mr=n=>(H("data-v-096ef0a5"),n=n(),E(),n),gr={class:"content"},yr={class:"outline-title"},br={"aria-labelledby":"doc-outline-aria-label"},$r=mr(()=>u("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),kr=g({__name:"VPDocAsideOutline",setup(n){const{frontmatter:e,theme:t}=V(),o=ge([]);J(()=>{o.value=Me(e.value.outline??t.value.outline)});const s=S(),r=S();return ea(s,r),(d,p)=>(a(),l("div",{class:C(["VPDocAsideOutline",{"has-outline":o.value.length>0}]),ref_key:"container",ref:s},[u("div",gr,[u("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),u("div",yr,P(i(Le)(i(t))),1),u("nav",br,[$r,h(Ce,{headers:o.value,root:!0},null,8,["headers"])])])],2))}});const Pr=f(kr,[["__scopeId","data-v-096ef0a5"]]),Vr={class:"VPDocAsideCarbonAds"},wr=g({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(n){const e=()=>null;return(t,o)=>(a(),l("div",Vr,[h(i(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),Sr=n=>(H("data-v-a773ec5b"),n=n(),E(),n),Lr={class:"VPDocAside"},Mr=Sr(()=>u("div",{class:"spacer"},null,-1)),Cr=g({__name:"VPDocAside",setup(n){const{theme:e}=V();return(t,o)=>(a(),l("div",Lr,[c(t.$slots,"aside-top",{},void 0,!0),c(t.$slots,"aside-outline-before",{},void 0,!0),h(Pr),c(t.$slots,"aside-outline-after",{},void 0,!0),Mr,c(t.$slots,"aside-ads-before",{},void 0,!0),i(e).carbonAds?(a(),y(wr,{key:0,"carbon-ads":i(e).carbonAds},null,8,["carbon-ads"])):m("",!0),c(t.$slots,"aside-ads-after",{},void 0,!0),c(t.$slots,"aside-bottom",{},void 0,!0)]))}});const Br=f(Cr,[["__scopeId","data-v-a773ec5b"]]);function Ir(){const{theme:n,page:e}=V();return $(()=>{const{text:t="Edit this page",pattern:o=""}=n.value.editLink||{};let s;return typeof o=="function"?s=o(e.value):s=o.replace(/:path/g,e.value.filePath),{url:s,text:t}})}function Nr(){const{page:n,theme:e,frontmatter:t}=V();return $(()=>{var d,p,_,b;const o=Oe(e.value.sidebar,n.value.relativePath),s=wt(o),r=s.findIndex(M=>K(n.value.relativePath,M.link));return{prev:t.value.prev===!1?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((d=s[r-1])==null?void 0:d.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((p=s[r-1])==null?void 0:p.link)},next:t.value.next===!1?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((_=s[r+1])==null?void 0:_.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((b=s[r+1])==null?void 0:b.link)}}})}const Tr={},Ar={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},xr=u("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),Hr=u("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),Er=[xr,Hr];function zr(n,e){return a(),l("svg",Ar,Er)}const Dr=f(Tr,[["render",zr]]),Fr={class:"VPLastUpdated"},Or=["datetime"],Gr=g({__name:"VPDocFooterLastUpdated",setup(n){const{theme:e,page:t,lang:o}=V(),s=$(()=>new Date(t.value.lastUpdated)),r=$(()=>s.value.toISOString()),d=S("");return F(()=>{Q(()=>{d.value=s.value.toLocaleString(o.value)})}),(p,_)=>(a(),l("p",Fr,[T(P(i(e).lastUpdatedText||"Last updated")+": ",1),u("time",{datetime:r.value},P(d.value),9,Or)]))}});const Rr=f(Gr,[["__scopeId","data-v-a02285cd"]]),Ur={key:0,class:"VPDocFooter"},jr={key:0,class:"edit-info"},qr={key:0,class:"edit-link"},Kr={key:1,class:"last-updated"},Wr={key:1,class:"prev-next"},Yr={class:"pager"},Xr=["href"],Qr=["innerHTML"],Jr=["innerHTML"],Zr=["href"],ei=["innerHTML"],ti=["innerHTML"],ni=g({__name:"VPDocFooter",setup(n){const{theme:e,page:t,frontmatter:o}=V(),s=Ir(),r=Nr(),d=$(()=>e.value.editLink&&o.value.editLink!==!1),p=$(()=>t.value.lastUpdated&&o.value.lastUpdated!==!1),_=$(()=>d.value||p.value||r.value.prev||r.value.next);return(b,M)=>{var I,w,k,N,x,B,D;return _.value?(a(),l("footer",Ur,[c(b.$slots,"doc-footer-before",{},void 0,!0),d.value||p.value?(a(),l("div",jr,[d.value?(a(),l("div",qr,[h(O,{class:"edit-link-button",href:i(s).url,"no-icon":!0},{default:v(()=>[h(Dr,{class:"edit-link-icon","aria-label":"edit icon"}),T(" "+P(i(s).text),1)]),_:1},8,["href"])])):m("",!0),p.value?(a(),l("div",Kr,[h(Rr)])):m("",!0)])):m("",!0),(I=i(r).prev)!=null&&I.link||(w=i(r).next)!=null&&w.link?(a(),l("div",Wr,[u("div",Yr,[(k=i(r).prev)!=null&&k.link?(a(),l("a",{key:0,class:"pager-link prev",href:i(Z)(i(r).prev.link)},[u("span",{class:"desc",innerHTML:((N=i(e).docFooter)==null?void 0:N.prev)||"Previous page"},null,8,Qr),u("span",{class:"title",innerHTML:i(r).prev.text},null,8,Jr)],8,Xr)):m("",!0)]),u("div",{class:C(["pager",{"has-prev":(x=i(r).prev)==null?void 0:x.link}])},[(B=i(r).next)!=null&&B.link?(a(),l("a",{key:0,class:"pager-link next",href:i(Z)(i(r).next.link)},[u("span",{class:"desc",innerHTML:((D=i(e).docFooter)==null?void 0:D.next)||"Next page"},null,8,ei),u("span",{class:"title",innerHTML:i(r).next.text},null,8,ti)],8,Zr)):m("",!0)],2)])):m("",!0)])):m("",!0)}}});const si=f(ni,[["__scopeId","data-v-0fee921e"]]),oi={key:0,class:"VPDocOutlineDropdown"},ai={key:0,class:"items"},ri=g({__name:"VPDocOutlineDropdown",setup(n){const{frontmatter:e,theme:t}=V(),o=S(!1);J(()=>{o.value=!1});const s=ge([]);return J(()=>{s.value=Me(e.value.outline??t.value.outline)}),(r,d)=>s.value.length>0?(a(),l("div",oi,[u("button",{onClick:d[0]||(d[0]=p=>o.value=!o.value),class:C({open:o.value})},[T(P(i(Le)(i(t)))+" ",1),h(Be,{class:"icon"})],2),o.value?(a(),l("div",ai,[h(Ce,{headers:s.value},null,8,["headers"])])):m("",!0)])):m("",!0)}});const ii=f(ri,[["__scopeId","data-v-115d6c42"]]),li=n=>(H("data-v-cbd4323a"),n=n(),E(),n),ci={class:"container"},ui=li(()=>u("div",{class:"aside-curtain"},null,-1)),di={class:"aside-container"},_i={class:"aside-content"},vi={class:"content"},pi={class:"content-container"},hi={class:"main"},fi=g({__name:"VPDoc",setup(n){const e=ee(),{hasSidebar:t,hasAside:o,leftAside:s}=z(),r=$(()=>e.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(d,p)=>{const _=R("Content");return a(),l("div",{class:C(["VPDoc",{"has-sidebar":i(t),"has-aside":i(o)}])},[c(d.$slots,"doc-top",{},void 0,!0),u("div",ci,[i(o)?(a(),l("div",{key:0,class:C(["aside",{"left-aside":i(s)}])},[ui,u("div",di,[u("div",_i,[h(Br,null,{"aside-top":v(()=>[c(d.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[c(d.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[c(d.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(d.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(d.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(d.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):m("",!0),u("div",vi,[u("div",pi,[c(d.$slots,"doc-before",{},void 0,!0),h(ii),u("main",hi,[h(_,{class:C(["vp-doc",r.value])},null,8,["class"])]),h(si,null,{"doc-footer-before":v(()=>[c(d.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),c(d.$slots,"doc-after",{},void 0,!0)])])]),c(d.$slots,"doc-bottom",{},void 0,!0)],2)}}});const mi=f(fi,[["__scopeId","data-v-cbd4323a"]]),ce=n=>(H("data-v-867fe174"),n=n(),E(),n),gi={class:"NotFound"},yi=ce(()=>u("p",{class:"code"},"404",-1)),bi=ce(()=>u("h1",{class:"title"},"PAGE NOT FOUND",-1)),$i=ce(()=>u("div",{class:"divider"},null,-1)),ki=ce(()=>u("blockquote",{class:"quote"}," But if you don't change your direction, and if you keep looking, you may end up where you are heading. ",-1)),Pi={class:"action"},Vi=["href"],wi=g({__name:"NotFound",setup(n){const{site:e}=V(),{localeLinks:t}=te({removeCurrent:!1}),o=S("/");return F(()=>{var r;const s=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");t.value.length&&(o.value=((r=t.value.find(({link:d})=>d.startsWith(s)))==null?void 0:r.link)||t.value[0].link)}),(s,r)=>(a(),l("div",gi,[yi,bi,$i,ki,u("div",Pi,[u("a",{class:"link",href:i(pe)(o.value),"aria-label":"go to home"}," Take me home ",8,Vi)])]))}});const Si=f(wi,[["__scopeId","data-v-867fe174"]]),Li=g({__name:"VPContent",setup(n){const{page:e,frontmatter:t}=V(),{hasSidebar:o}=z();return(s,r)=>(a(),l("div",{class:C(["VPContent",{"has-sidebar":i(o),"is-home":i(t).layout==="home"}]),id:"VPContent"},[i(e).isNotFound?c(s.$slots,"not-found",{key:0},()=>[h(Si)],!0):i(t).layout==="page"?(a(),y(Ia,{key:1},{"page-top":v(()=>[c(s.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[c(s.$slots,"page-bottom",{},void 0,!0)]),_:3})):i(t).layout==="home"?(a(),y(fr,{key:2},{"home-hero-before":v(()=>[c(s.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[c(s.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[c(s.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[c(s.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[c(s.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[c(s.$slots,"home-features-after",{},void 0,!0)]),_:3})):(a(),y(mi,{key:3},{"doc-top":v(()=>[c(s.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[c(s.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":v(()=>[c(s.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[c(s.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[c(s.$slots,"doc-after",{},void 0,!0)]),"aside-top":v(()=>[c(s.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":v(()=>[c(s.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(s.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(s.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(s.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":v(()=>[c(s.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}});const Mi=f(Li,[["__scopeId","data-v-c954fd0c"]]),Ci={class:"container"},Bi=["innerHTML"],Ii=["innerHTML"],Ni=g({__name:"VPFooter",setup(n){const{theme:e}=V(),{hasSidebar:t}=z();return(o,s)=>i(e).footer?(a(),l("footer",{key:0,class:C(["VPFooter",{"has-sidebar":i(t)}])},[u("div",Ci,[i(e).footer.message?(a(),l("p",{key:0,class:"message",innerHTML:i(e).footer.message},null,8,Bi)):m("",!0),i(e).footer.copyright?(a(),l("p",{key:1,class:"copyright",innerHTML:i(e).footer.copyright},null,8,Ii)):m("",!0)])],2)):m("",!0)}});const Ti=f(Ni,[["__scopeId","data-v-f3a6e121"]]),Ai={key:0,class:"Layout"},xi=g({__name:"Layout",setup(n){const{isOpen:e,open:t,close:o}=z(),s=ee();q(()=>s.path,o),St(e,o),oe("close-sidebar",o),oe("is-sidebar-open",e);const{frontmatter:r}=V(),d=vt(),p=$(()=>!!d["home-hero-image"]);return oe("hero-image-slot-exists",p),(_,b)=>{const M=R("Content");return i(r).layout!==!1?(a(),l("div",Ai,[c(_.$slots,"layout-top",{},void 0,!0),h(Ct),h(Nt,{class:"backdrop",show:i(e),onClick:i(o)},null,8,["show","onClick"]),h(Fo,null,{"nav-bar-title-before":v(()=>[c(_.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(_.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[c(_.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[c(_.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":v(()=>[c(_.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[c(_.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),h(ha,{open:i(e),onOpenMenu:i(t)},null,8,["open","onOpenMenu"]),h(La,{open:i(e)},{"sidebar-nav-before":v(()=>[c(_.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":v(()=>[c(_.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),h(Mi,null,{"page-top":v(()=>[c(_.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[c(_.$slots,"page-bottom",{},void 0,!0)]),"not-found":v(()=>[c(_.$slots,"not-found",{},void 0,!0)]),"home-hero-before":v(()=>[c(_.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[c(_.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[c(_.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[c(_.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[c(_.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[c(_.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":v(()=>[c(_.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[c(_.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[c(_.$slots,"doc-after",{},void 0,!0)]),"doc-top":v(()=>[c(_.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[c(_.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":v(()=>[c(_.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[c(_.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[c(_.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(_.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(_.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(_.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),h(Ti),c(_.$slots,"layout-bottom",{},void 0,!0)])):(a(),y(M,{key:1}))}}});const Hi=f(xi,[["__scopeId","data-v-1a0cf8a6"]]);const zi={Layout:Hi,enhanceApp:({app:n})=>{n.component("Badge",ht)}};export{zi as t}; diff --git a/assets/configuration_index.md.81fa051a.js b/assets/configuration_index.md.81fa051a.js new file mode 100644 index 00000000..21c00e59 --- /dev/null +++ b/assets/configuration_index.md.81fa051a.js @@ -0,0 +1,14 @@ +import{_ as s,o as a,c as n,O as e}from"./chunks/framework.2958c35d.js";const C=JSON.parse('{"title":"Configuration","description":"","frontmatter":{},"headers":[],"relativePath":"configuration/index.md","filePath":"configuration/index.md"}'),t={name:"configuration/index.md"},o=e(`

Configuration

INFO

The default configuration is great for most users. You might not need to tweak anything here.

The authorization server has a few optional settings with the following default values;

ts
type AuthorizationServerOptions = {
+  requiresPKCE: true;
+  requiresS256: false;
+  notBeforeLeeway: 0;
+  tokenCID: "id" | "name";
+}
OptionNumberDefaultDetails
requiresPKCEbooleantruePKCE is enabled by default and recommended for all users. To support a legacy client without PKCE, disable this option. [Learn more]
requiresS256booleantrueDisabled by default. If you want to require all clients to use S256, you can enable that here. [Learn more]
notBeforeLeewaynumber0Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a NumericDate value.
tokenCID"id" or "name""id"Sets the JWT accessToken.cid to either the client.id or client.name.

In 3.x the default is "id", in v2.x the default was "name". [Learn more]

To configure these options, pass the value in as the last argument:

typescript
const authorizationServer = new AuthorizationServer(
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  new JwtService("secret-key"),
+  {
+    requiresS256: true,
+  }
+);
`,7),l=[o];function p(r,c,i,d,D,y){return a(),n("div",null,l)}const F=s(t,[["render",p]]);export{C as __pageData,F as default}; diff --git a/assets/configuration_index.md.81fa051a.lean.js b/assets/configuration_index.md.81fa051a.lean.js new file mode 100644 index 00000000..87044d3c --- /dev/null +++ b/assets/configuration_index.md.81fa051a.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as n,O as e}from"./chunks/framework.2958c35d.js";const C=JSON.parse('{"title":"Configuration","description":"","frontmatter":{},"headers":[],"relativePath":"configuration/index.md","filePath":"configuration/index.md"}'),t={name:"configuration/index.md"},o=e("",7),l=[o];function p(r,c,i,d,D,y){return a(),n("div",null,l)}const F=s(t,[["render",p]]);export{C as __pageData,F as default}; diff --git a/assets/entities_index.md.ba015854.js b/assets/entities_index.md.ba015854.js new file mode 100644 index 00000000..d1af976e --- /dev/null +++ b/assets/entities_index.md.ba015854.js @@ -0,0 +1,32 @@ +import{_ as s,o as n,c as a,O as l}from"./chunks/framework.2958c35d.js";const A=JSON.parse('{"title":"Entity Interfaces","description":"","frontmatter":{"title":"Entity Interfaces"},"headers":[],"relativePath":"entities/index.md","filePath":"entities/index.md"}'),e={name:"entities/index.md"},o=l(`

Entity Interfaces

Client Entity

This entity represents the client that wants to access the resource server. The client will retrieve an access token from our authorization server and use it to access the resource server.

  • URI must be an absolute URI
  • The endpoint may include application/x-www-form-urlencoded formatted query component which must be retained when adding additional query params
  • the endpoint URI must not include a fragment component
typescript
interface OAuthClient {
+  id: string;
+  name: string;
+  secret?: string;
+  redirectUris: string[];
+  allowedGrants: GrantIdentifier[];
+  scopes: OAuthScope[];
+}

Auth Code Entity

The auth code is used to retrieve an access token from the authorization server.

typescript
interface OAuthAuthCode {
+  code: string;
+  redirectUri?: string;
+  codeChallenge?: string;
+  codeChallengeMethod?: CodeChallengeMethod;
+  expiresAt: Date;
+  user?: OAuthUser;
+  client: OAuthClient;
+  scopes: OAuthScope[];
+}

TIP

ts
type CodeChallengeMethod = "S256" | "plain";

Token Entity

The access and refresh token that can be used to authenticate into the resource server. The originatingAuthCodeId will be present only for tokens originating from the authorization code grant; see the revokeDescendantsOf() method on the Token Repository for its significance.

typescript
interface OAuthToken {
+  accessToken: string;
+  accessTokenExpiresAt: Date;
+  refreshToken?: string | null;
+  refreshTokenExpiresAt?: Date | null;
+  client: OAuthClient;
+  user?: OAuthUser | null;
+  scopes: OAuthScope[];
+  originatingAuthCodeId?: string;
+}

User Entity

The resource owner

typescript
interface OAuthUser {
+  id: string;
+  [key: string]: any;
+}

Scope Entity

Scopes are a way to limit an app’s access to a user’s data.

https://www.oauth.com/oauth2-servers/scope/

typescript
interface OAuthScope {
+  name: string;
+  [key: string]: any;
+}
`,19),p=[o];function t(c,r,y,i,F,C){return n(),a("div",null,p)}const h=s(e,[["render",t]]);export{A as __pageData,h as default}; diff --git a/assets/entities_index.md.ba015854.lean.js b/assets/entities_index.md.ba015854.lean.js new file mode 100644 index 00000000..a42d89c2 --- /dev/null +++ b/assets/entities_index.md.ba015854.lean.js @@ -0,0 +1 @@ +import{_ as s,o as n,c as a,O as l}from"./chunks/framework.2958c35d.js";const A=JSON.parse('{"title":"Entity Interfaces","description":"","frontmatter":{"title":"Entity Interfaces"},"headers":[],"relativePath":"entities/index.md","filePath":"entities/index.md"}'),e={name:"entities/index.md"},o=l("",19),p=[o];function t(c,r,y,i,F,C){return n(),a("div",null,p)}const h=s(e,[["render",t]]);export{A as __pageData,h as default}; diff --git a/assets/getting_started_index.md.f2de24b4.js b/assets/getting_started_index.md.f2de24b4.js new file mode 100644 index 00000000..883d0d64 --- /dev/null +++ b/assets/getting_started_index.md.f2de24b4.js @@ -0,0 +1,72 @@ +import{_ as s,o as a,c as n,O as o}from"./chunks/framework.2958c35d.js";const C=JSON.parse('{"title":"Getting Started","description":"","frontmatter":{},"headers":[],"relativePath":"getting_started/index.md","filePath":"getting_started/index.md"}'),l={name:"getting_started/index.md"},p=o(`

Getting Started

Install

npm

bash
pnpm add @jmondi/oauth2-server
bash
npm install --save @jmondi/oauth2-server
bash
yarn add @jmondi/oauth2-server

The Authorization Server

The AuthorizationServer depends on the repositories. By default, no grants are enabled; each grant is opt-in and must be enabled when creating the AuthorizationServer.

You can enable any grant types you would like to support.

typescript
const authorizationServer = new AuthorizationServer(
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  "secret-key",
+  {} // optional configuration
+);
+authorizationServer.enableGrantType("client_credentials");
+authorizationServer.enableGrantType("refresh_token");
+authorizationServer.enableGrantType({
+  grant: "authorization_code",
+  userRepository, 
+  authorizationCodeRepository,
+});

See the configuration documentation for a full list of config options.

The Token Endpoint

The /token endpoint is a back channel endpoint that issues a usable access token.

typescript
app.post("/token", async (req: Express.Request, res: Express.Response) => {
+  try {
+    const oauthResponse = await authorizationServer.respondToAccessTokenRequest(req);
+    return handleExpressResponse(res, oauthResponse);
+  } catch (e) {
+    handleExpressError(e, res);
+    return;
+  }
+});

The Authorize Endpoint

The /authorize endpoint is a front channel endpoint that issues an authorization code. The authorization code can then be exchanged to the AuthorizationServer endpoint for a useable access token.

The endpoint should redirect the user to login, and then to accept the scopes requested by the application, and only when the user accepts, should it send the user back to the clients redirect uri.

typescript
import { requestFromExpress } from "@jmondi/oauth2-server/express";
+
+app.get("/authorize", async (req: Express.Request, res: Express.Response) => {
+  try {
+    // Validate the HTTP request and return an AuthorizationRequest.
+    const authRequest = await authorizationServer.validateAuthorizationRequest(request, requestFromExpress(req));
+
+    // You will probably redirect the user to a login endpoint. 
+    if (!req.user) {
+      req.redirect("/login")
+      return;
+    }
+    // After login, the user should be redirected back with user in the session.
+    // You will need to manage the authorization query on the round trip.
+    // The auth request object can be serialized and saved into a user's session.
+
+    // Once the user has logged in set the user on the AuthorizationRequest
+    authRequest.user = req.user;
+    
+    // Once the user has approved or denied the client update the status
+    // (true = approved, false = denied)
+    authRequest.isAuthorizationApproved = getIsAuthorizationApprovedFromSession();
+
+    // If the user has not approved the client's authorization request, 
+    // the user should be redirected to the approval screen.
+    if (!authRequest.isAuthorizationApproved) {
+      // This form will ask the user to approve the client and the scopes requested.
+      // "Do you authorize Jason to: read contacts? write contacts?"
+      req.redirect("/scopes")
+      return;
+    }
+
+    // At this point the user has approved the client for authorization.
+    // Any last authorization requests such as Two Factor Authentication (2FA) can happen here.
+
+
+    // Redirect back to redirect_uri with \`code\` and \`state\` as url query params.
+    const oauthResponse = await authorizationServer.completeAuthorizationRequest(authRequest);
+    return handleExpressResponse(res, oauthResponse);
+  } catch (e) {
+    handleExpressError(e, res);
+  }
+});

Revoke Token

Note

Implementing this endpoint is optional, but recommended. RFC7009 “OAuth 2.0 Token Revocation”

The /token/revoke endpoint is a back channel endpoint that revokes an existing token.

typescript
app.post("/token/revoke", async (req: Express.Request, res: Express.Response) => {
+  try {
+    const oauthResponse = await authorizationServer.revoke(req);
+    return handleExpressResponse(res, oauthResponse);
+  } catch (e) {
+    handleExpressError(e, res);
+    return;
+  }
+});
`,20),e=[p];function t(r,c,y,F,i,D){return a(),n("div",null,e)}const h=s(l,[["render",t]]);export{C as __pageData,h as default}; diff --git a/assets/getting_started_index.md.f2de24b4.lean.js b/assets/getting_started_index.md.f2de24b4.lean.js new file mode 100644 index 00000000..79933c7c --- /dev/null +++ b/assets/getting_started_index.md.f2de24b4.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as n,O as o}from"./chunks/framework.2958c35d.js";const C=JSON.parse('{"title":"Getting Started","description":"","frontmatter":{},"headers":[],"relativePath":"getting_started/index.md","filePath":"getting_started/index.md"}'),l={name:"getting_started/index.md"},p=o("",20),e=[p];function t(r,c,y,F,i,D){return a(),n("div",null,e)}const h=s(l,[["render",t]]);export{C as __pageData,h as default}; diff --git a/assets/glossary_index.md.52c4ef34.js b/assets/glossary_index.md.52c4ef34.js new file mode 100644 index 00000000..a6a8ad47 --- /dev/null +++ b/assets/glossary_index.md.52c4ef34.js @@ -0,0 +1 @@ +import{_ as a,o as r,c as s,z as e,a as o,t as n,O as i}from"./chunks/framework.2958c35d.js";const x=JSON.parse('{"title":"Glossary","description":"","frontmatter":{"title":"Glossary"},"headers":[],"relativePath":"glossary/index.md","filePath":"glossary/index.md"}'),c={name:"glossary/index.md"},l={id:"frontmatter-title",tabindex:"-1"},h=e("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{ $frontmatter.title }}"'},"​",-1),d=i('

Resource Server

The resource server is the OAuth 2.0 term for your API server. The resource server handles authenticated requests after the client has obtained an access token.

Client

The application attempting to gain access to the resource server. The client must have an OAuthClient

',4);function _(t,u,m,p,f,v){return r(),s("div",null,[e("h1",l,[o(n(t.$frontmatter.title)+" ",1),h]),d])}const y=a(c,[["render",_]]);export{x as __pageData,y as default}; diff --git a/assets/glossary_index.md.52c4ef34.lean.js b/assets/glossary_index.md.52c4ef34.lean.js new file mode 100644 index 00000000..5bdcece3 --- /dev/null +++ b/assets/glossary_index.md.52c4ef34.lean.js @@ -0,0 +1 @@ +import{_ as a,o as r,c as s,z as e,a as o,t as n,O as i}from"./chunks/framework.2958c35d.js";const x=JSON.parse('{"title":"Glossary","description":"","frontmatter":{"title":"Glossary"},"headers":[],"relativePath":"glossary/index.md","filePath":"glossary/index.md"}'),c={name:"glossary/index.md"},l={id:"frontmatter-title",tabindex:"-1"},h=e("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{ $frontmatter.title }}"'},"​",-1),d=i("",4);function _(t,u,m,p,f,v){return r(),s("div",null,[e("h1",l,[o(n(t.$frontmatter.title)+" ",1),h]),d])}const y=a(c,[["render",_]]);export{x as __pageData,y as default}; diff --git a/assets/grants_authorization_code.md.a6daa690.js b/assets/grants_authorization_code.md.a6daa690.js new file mode 100644 index 00000000..492ccef0 --- /dev/null +++ b/assets/grants_authorization_code.md.a6daa690.js @@ -0,0 +1,50 @@ +import{_ as s,o as a,c as n,O as o}from"./chunks/framework.2958c35d.js";const A=JSON.parse('{"title":"Authorization Code Grant (w/ PKCE)","description":"","frontmatter":{},"headers":[],"relativePath":"grants/authorization_code.md","filePath":"grants/authorization_code.md"}'),e={name:"grants/authorization_code.md"},l=o(`

Authorization Code Grant (w/ PKCE)

A temporary code that the client will exchange for an access token. The user authorizes the application, they are redirected back to the application with a temporary code in the URL. The application exchanges that code for the access token.

Flow

Part One

The client redirects the user to the /authorize with the following query parameters:

  • response_type must be set to code
  • client_id is the client identifier you received when you first created the application
  • redirect_uri indicates the URL to return the user to after authorization is complete, such as org.example.app://redirect
  • state is a random string generated by your application, which you’ll verify later
  • code_challenge must match the The code challenge as generated below,
  • code_challenge_method – Either plain or S256, depending on whether the challenge is the plain verifier string or the SHA256 hash of the string. If this parameter is omitted, the server will assume plain.

TIP

The client secret should never be used during the Part One of the authorization_code flow.

View sample authorization_code (part 1) request
http
GET /authorize HTTP/1.1
+Host: example.com
+
+response_type=code
+&client_id=xxxxxxx
+&redirect_uri=http://localhost
+&scope="contacts.read contacts.write"
+&state=abcdefghijklmnopqrstuvwxyz123456789
+&code_challenge=92d3b56942866d1edf02c33339b7c3dc37c6201282bb238cb47f0d3289f28a93f1bdd8af6ca9913aed0c4c
+&code_challenge_method=S256

The user will be asked to login to the authorization server and approve the client and requested scopes.

If the user approves the client, they will be redirected from the authorization server to the provided redirect_uri with the following fields in the query string:

  • code is the authorization code that will soon be exchanged for a token
  • state is the random string provided and should be compared against the initially provided state
View sample authorization_code (part 1) response
http
HTTP/1.1 302 Found
+Location: http://localhost&code=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRfaWQiOiJhdXRoY29kZWNsaWVudCIsInJlZGlyZWN0X3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3QiLCJhdXRoX2NvZGVfaWQiOiJteS1zdXBlci1zZWNyZXQtYXV0aC1jb2RlIiwic2NvcGVzIjpbXSwiZXhwaXJlX3RpbWUiOjE2MDE3NTM3MzMsImNvZGVfY2hhbGxlbmdlIjoiT0RRd1pHTTRZelpsTnpNeU1qUXlaREF4WWpFNU1XWmtZMlJrTmpKbU1UbGxNbUkwTnpJMFpEbGtNR0psWWpGbE1tTXhPV1kyWkRJMVpEZGpNak13WWciLCJjb2RlX2NoYWxsZW5nZV9tZXRob2QiOiJTMjU2In0.OIEtZN5BHNaB4Mz0plUpGAP93EHyoil2smJiG3S_2BM&state=abcdefghijklmnopqrstuvwxyz123456789

Part Two

The client sends a POST to the /token endpoint with the following body:

  • grant_type must be set to authorization_code
  • client_id is the client identifier you received when you first created the application
  • client_secret (optional) is the client secret and should only be provided if the client is confidential
  • redirect_uri
  • code_verifier
  • code is the authorization code from the query string

Private Key Leak Potential

Clients such as Browser Based Apps and Native Mobile Apps should NEVER have or use a client_secret. That means the client_secret should be omitted both when initially creating the OAuthClient entity, and when making requests.

View sample authorization_code (part 2) request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=authorization_code
+&client_id=xxxxxxxxxx
+&client_secret=xxxxxxxxxx
+&redirect_uri=http://localhost
+&code_verifier=OTJkM2I1Njk0Mjg2NmQxZWRmMDJjMzMzMzliN2MzZGMzN2M2MjAxMjgyYmIyMzhjYjQ3ZjBkMzI4OWYyOGE5M2YxYmRkOGFmNmNhOTkxM2FlZDBjNGM
+&code=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRfaWQiOiJhdXRoY29kZWNsaWVudCIsInJlZGlyZWN0X3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3QiLCJhdXRoX2NvZGVfaWQiOiJteS1zdXBlci1zZWNyZXQtYXV0aC1jb2RlIiwic2NvcGVzIjpbXSwiZXhwaXJlX3RpbWUiOjE2MDE3NTM3MzMsImNvZGVfY2hhbGxlbmdlIjoiT0RRd1pHTTRZelpsTnpNeU1qUXlaREF4WWpFNU1XWmtZMlJrTmpKbU1UbGxNbUkwTnpJMFpEbGtNR0psWWpGbE1tTXhPV1kyWkRJMVpEZGpNak13WWciLCJjb2RlX2NoYWxsZW5nZV9tZXRob2QiOiJTMjU2In0.OIEtZN5BHNaB4Mz0plUpGAP93EHyoil2smJiG3S_2BM

The authorization server will respond with the following response

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and is used to authenticate into the resource server
  • refresh_token is a JWT signed token and can be used in with the refresh grant
  • scope is a space delimited list of scopes the token has access to
View sample authorization_code (part 2) response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDE3NTUxMDQsIm5iZiI6MTYwMTc1MTUwNCwiaWF0IjoxNjAxNzUxNTA0LCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGF1dGggY29kZSBjbGllbnQiLCJzY29wZSI6IiJ9.-V9x03iz-3ISRMdj9m1-FCKjmtfjvv6wqnBj6VZdW28',
+  refresh_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiJhdXRoY29kZWNsaWVudCIsImFjY2Vzc190b2tlbl9pZCI6Im5ldyB0b2tlbiIsInJlZnJlc2hfdG9rZW5faWQiOiJ0aGlzLWlzLW15LXN1cGVyLXNlY3JldC1yZWZyZXNoLXRva2VuIiwic2NvcGUiOiIiLCJleHBpcmVfdGltZSI6MTYwMTc1NTEwNCwiaWF0IjoxNjAxNzUxNTAzfQ.J_RUFD5-158atTmI98R95vowZWi4mUEXYCO7iNwzpK4',
+  scope: 'contacts.read contacts.write'
+}

PKCE

PKCE (RFC 7636) is an extension to the Authorization Code flow to prevent several attacks and to be able to securely perform the OAuth exchange from public clients.

By default, PKCE is enabled and encouraged for all users. If you need to support a legacy client system without PKCE, you can disable PKCE with the authorization server using the requiresPKCE configuration option.

Code Verifier

The code_verifier is part of the extended “PKCE” and helps mitigate the threat of having authorization codes intercepted.

Before initializing Part One of the authorization code flow, the client first creats a code_verifier. This is a cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long.

We can do this in Node using the native crypto package and a base64urlencode function:

typescript
import crypto from "node:crypto";
+
+const code_verifier = crypto.randomBytes(43).toString("hex");

@see https://www.oauth.com/oauth2-servers/pkce/authorization-request/

Code Challenge

Now we need to create a code_challenge from our code_verifier.

For devices that can perform a SHA256 hash, the code challenge is a BASE64-URL-encoded string of the SHA256 hash of the code verifier.

typescript
const code_challenge = base64urlencode(
+  crypto.createHash("sha256")
+    .update(code_verifier)
+    .digest()
+);

Clients that do not have the ability to perform a SHA256 hash are permitted to use the plain code_verifier string as the code_challenge.

typescript
const code_challenge = code_verifier;
Need a base64urlencode function?
typescript
function base64urlencode(str: string) {
+  return Buffer.from(str)
+    .toString("base64")
+    .replace(/\\+/g, "-")
+    .replace(/\\//g, "_")
+    .replace(/=/g, "");
+}

Revocation

Authorization codes are only valid for a single use. In addition, they can be explicitly revoked on a server that supports RFC7009 “OAuth 2.0 Token Revocation”.

An authorization code revocation request will include the following parameters:

  • token is the authorization code previously issued to the client
  • token_type_hint (optional) should be set to authorization_code
View sample revoke authorization_code request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+token_type_hint=authorization_code
+&refresh_token=xxxxxxxxx

The authorization server will respond with the following response

View sample revoke authorization_code response
http
HTTP/1.1 200 OK
+Cache-Control: no-store
+Pragma: no-cache
`,43),t=[l];function p(r,c,i,C,y,d){return a(),n("div",null,t)}const D=s(e,[["render",p]]);export{A as __pageData,D as default}; diff --git a/assets/grants_authorization_code.md.a6daa690.lean.js b/assets/grants_authorization_code.md.a6daa690.lean.js new file mode 100644 index 00000000..8cf271b7 --- /dev/null +++ b/assets/grants_authorization_code.md.a6daa690.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as n,O as o}from"./chunks/framework.2958c35d.js";const A=JSON.parse('{"title":"Authorization Code Grant (w/ PKCE)","description":"","frontmatter":{},"headers":[],"relativePath":"grants/authorization_code.md","filePath":"grants/authorization_code.md"}'),e={name:"grants/authorization_code.md"},l=o("",43),t=[l];function p(r,c,i,C,y,d){return a(),n("div",null,t)}const D=s(e,[["render",p]]);export{A as __pageData,D as default}; diff --git a/assets/grants_client_credentials.md.c56b9192.js b/assets/grants_client_credentials.md.c56b9192.js new file mode 100644 index 00000000..dbc8689b --- /dev/null +++ b/assets/grants_client_credentials.md.c56b9192.js @@ -0,0 +1,23 @@ +import{_ as s,o as a,c as n,O as e}from"./chunks/framework.2958c35d.js";const D=JSON.parse('{"title":"Client Credentials Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/client_credentials.md","filePath":"grants/client_credentials.md"}'),l={name:"grants/client_credentials.md"},o=e(`

Client Credentials Grant

When applications request an access token to access their own resources, not on behalf of a user.

TIP

The client_credentials grant should only be used by clients that can hold a secret. No Browser or Native Mobile Apps should be using this grant.

Flow

The client sends a POST to the /token endpoint with the following body:

  • grant_type must be set to client_credentials
  • client_id is the client identifier you received when you first created the application
  • client_secret is the client secret
  • scope is a string with a space delimited list of requested scopes. The requested scopes must be valid for the client.
View sample client_credentials request

Did you know? You can authenticate by passing the client_id and client_secret as a query string, or through basic auth.

http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=client_credentials
+&client_id=xxxxxxxxxx
+&client_secret=xxxxxxxxxx
+&scope="contacts.read contacts.write"
http
POST /token HTTP/1.1
+Host: example.com
+Authorization: Basic MTpzdXBlci1zZWNyZXQtc2VjcmV0
+
+grant_type=client_credentials
+&scope="contacts.read contacts.write"

The authorization server will respond with the following response.

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and can be used to authenticate into the resource server
  • scope is a space delimited list of scopes the token has access to
View sample client_credentials response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+ 
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDE3MDY0NjYsIm5iZiI6MTYwMTcwMjg2NiwiaWF0IjoxNjAxNzAyODY2LCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGNsaWVudCIsInNjb3BlIjoiIn0.KcXoCP6u9uhvtOoistLBskESA0tyT2I1SDe5Yn9iM4I',
+  scope: 'contacts.create contacts.read'
+}
`,10),t=[o];function p(c,r,i,C,y,d){return a(),n("div",null,t)}const F=s(l,[["render",p]]);export{D as __pageData,F as default}; diff --git a/assets/grants_client_credentials.md.c56b9192.lean.js b/assets/grants_client_credentials.md.c56b9192.lean.js new file mode 100644 index 00000000..8ad08c34 --- /dev/null +++ b/assets/grants_client_credentials.md.c56b9192.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as n,O as e}from"./chunks/framework.2958c35d.js";const D=JSON.parse('{"title":"Client Credentials Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/client_credentials.md","filePath":"grants/client_credentials.md"}'),l={name:"grants/client_credentials.md"},o=e("",10),t=[o];function p(c,r,i,C,y,d){return a(),n("div",null,t)}const F=s(l,[["render",p]]);export{D as __pageData,F as default}; diff --git a/assets/grants_implicit.md.7f4193d4.js b/assets/grants_implicit.md.7f4193d4.js new file mode 100644 index 00000000..82a8a168 --- /dev/null +++ b/assets/grants_implicit.md.7f4193d4.js @@ -0,0 +1 @@ +import{_ as t,o as e,c as a,O as i}from"./chunks/framework.2958c35d.js";const u=JSON.parse('{"title":"Implicit Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/implicit.md","filePath":"grants/implicit.md"}'),r={name:"grants/implicit.md"},o=i('

Implicit Grant

Not Recommended

Using the Implicit Grant is no longer best practice

This grant is supported, but not documented. Industry best practice recommends using the Authorization Code Grant without a client secret for native and browser-based apps.

Please look at these great resources:

',5),l=[o];function c(n,s,p,m,d,h){return e(),a("div",null,l)}const f=t(r,[["render",c]]);export{u as __pageData,f as default}; diff --git a/assets/grants_implicit.md.7f4193d4.lean.js b/assets/grants_implicit.md.7f4193d4.lean.js new file mode 100644 index 00000000..67f6d0b0 --- /dev/null +++ b/assets/grants_implicit.md.7f4193d4.lean.js @@ -0,0 +1 @@ +import{_ as t,o as e,c as a,O as i}from"./chunks/framework.2958c35d.js";const u=JSON.parse('{"title":"Implicit Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/implicit.md","filePath":"grants/implicit.md"}'),r={name:"grants/implicit.md"},o=i("",5),l=[o];function c(n,s,p,m,d,h){return e(),a("div",null,l)}const f=t(r,[["render",c]]);export{u as __pageData,f as default}; diff --git a/assets/grants_index.md.0db0021a.js b/assets/grants_index.md.0db0021a.js new file mode 100644 index 00000000..ae5ff05e --- /dev/null +++ b/assets/grants_index.md.0db0021a.js @@ -0,0 +1,39 @@ +import{_ as a,o as e,c as t,z as s,a as l,t as o,O as r}from"./chunks/framework.2958c35d.js";const D=JSON.parse('{"title":"Which Grant?","description":"","frontmatter":{"title":"Which Grant?"},"headers":[],"relativePath":"grants/index.md","filePath":"grants/index.md"}'),p={name:"grants/index.md"},c={id:"frontmatter-title",tabindex:"-1"},i=s("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{ $frontmatter.title }}"'},"​",-1),h=r(`

Grants are different ways a client can obtain an access_token that will authorize it to use the resource server.

Deciding which grant to use depends on the type of client the end user will be using.

+-------+
+| Start |
++-------+
+    V
+    |
+    
+    |
++------------------------+              +-----------------------+
+| Have a refresh token?  |>----Yes----->|  Refresh Token Grant  |
++------------------------+              +-----------------------+
+    V
+    |
+    No
+    |
++---------------------+                
+|     Who is the      |                  +--------------------------+
+| Access token owner? |>---A Machine---->| Client Credentials Grant |
++---------------------+                  +--------------------------+
+    V
+    |
+    |
+   A User
+    |
+    |
++----------------------+                
+| What type of client? |   
++----------------------+     
+    |
+    |                                 +---------------------------+
+    |>-----------Server App---------->| Auth Code Grant with PKCE |
+    |                                 +---------------------------+
+    |
+    |                                 +---------------------------+
+    |>-------Browser Based App------->| Auth Code Grant with PKCE |
+    |                                 +---------------------------+
+    |
+    |                                 +---------------------------+
+    |>-------Native Mobile App------->| Auth Code Grant with PKCE |
+                                      +---------------------------+

Refresh Token Grant

If the client already has a refresh token, it can use the Refresh Token Grant to obtain a new access token without requiring the user's interaction. This grant is useful for long-lived sessions and background processes.

Client Credentials Grant

If the access token owner is a machine, such as a server or an application acting on its own behalf, rather than an individual user, the client can use the Client Credentials Grant. This grant is designed for scenarios where the client needs to access resources autonomously without the context of a specific user.

Auth Code Grant with PKCE

If the access token owner is a user, the recommended grant is the Authorization Code Grant with Proof Key for Code Exchange (PKCE). This grant involves a series of steps where the client redirects the user to the authorization server, the user grants access, and the server provides an authorization code that the client exchanges for an access token. PKCE adds an extra layer of security to protect against authorization code interception attacks.

`,9);function C(n,A,d,u,y,f){return e(),t("div",null,[s("h1",c,[l(o(n.$frontmatter.title)+" ",1),i]),h])}const _=a(p,[["render",C]]);export{D as __pageData,_ as default}; diff --git a/assets/grants_index.md.0db0021a.lean.js b/assets/grants_index.md.0db0021a.lean.js new file mode 100644 index 00000000..40b63599 --- /dev/null +++ b/assets/grants_index.md.0db0021a.lean.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as t,z as s,a as l,t as o,O as r}from"./chunks/framework.2958c35d.js";const D=JSON.parse('{"title":"Which Grant?","description":"","frontmatter":{"title":"Which Grant?"},"headers":[],"relativePath":"grants/index.md","filePath":"grants/index.md"}'),p={name:"grants/index.md"},c={id:"frontmatter-title",tabindex:"-1"},i=s("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{ $frontmatter.title }}"'},"​",-1),h=r("",9);function C(n,A,d,u,y,f){return e(),t("div",null,[s("h1",c,[l(o(n.$frontmatter.title)+" ",1),i]),h])}const _=a(p,[["render",C]]);export{D as __pageData,_ as default}; diff --git a/assets/grants_password.md.94ac36b5.js b/assets/grants_password.md.94ac36b5.js new file mode 100644 index 00000000..3e02f233 --- /dev/null +++ b/assets/grants_password.md.94ac36b5.js @@ -0,0 +1,28 @@ +import{_ as s,o as a,c as n,O as l}from"./chunks/framework.2958c35d.js";const F=JSON.parse('{"title":"Password Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/password.md","filePath":"grants/password.md"}'),o={name:"grants/password.md"},p=l(`

Password Grant

The Password Grant is for first party clients that are able to hold secrets (ie not Browser or Native Mobile Apps)

TIP

The client_credentials grant should only be used by clients that can hold a secret

Flow

A complete refresh token request will include the following parameters:

  • grant_type must be set to password
  • client_id is the client identifier you received when you first created the application
  • client_secret if the client is confidential (has a secret), this must be provided
  • username
  • password
  • scope (optional)
View sample password grant request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=password
+&client_id=xxxxxxxxx
+&client_secret=xxxxxxxxx
+&username=xxxxxxxxx
+&password=xxxxxxxxx
+&scope="contacts.read contacts.write"
http
POST /token HTTP/1.1
+Host: example.com
+Authorization: Basic Y4NmE4MzFhZGFkNzU2YWRhN
+
+grant_type=password
+&username=xxxxxxxxx
+&password=xxxxxxxxx
+&scope="contacts.read contacts.write"

The authorization server will respond with the following response

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and is used to authenticate into the resource server
  • refresh_token is a JWT signed token and can be used in with the refresh grant
  • scope is a space delimited list of scopes the token has access to
View sample password grant response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1MTJhYjlhNC1jNzg2LTQ4YTYtOGFkNi05NGM1M2E4ZGM2NTEiLCJleHAiOjE2MDE3NjcyOTksIm5iZiI6MTYwMTc2MzY5OSwiaWF0IjoxNjAxNzYzNjk5LCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGNsaWVudCIsInNjb3BlIjoiIn0.sX6SWc2Af8jn-izFnrLgNIcNuZz_tRLl2p7M3CzQwKg',
+  refresh_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIzNTYxNWYyZi0xM2ZhLTQ3MzEtODNhMS05ZTM0NTU2YWIzOTAiLCJhY2Nlc3NfdG9rZW5faWQiOiJuZXcgdG9rZW4iLCJyZWZyZXNoX3Rva2VuX2lkIjoidGhpcy1pcy1teS1zdXBlci1zZWNyZXQtcmVmcmVzaC10b2tlbiIsInNjb3BlIjoiIiwidXNlcl9pZCI6IjUxMmFiOWE0LWM3ODYtNDhhNi04YWQ2LTk0YzUzYThkYzY1MSIsImV4cGlyZV90aW1lIjoxNjAxNzY3Mjk5LCJpYXQiOjE2MDE3NjM2OTh9.SSa7miIdk3bxyzg0f3M9jKBXWjPgD4QEw-AU3SYvBk0',
+  scope: 'contacts.read contacts.write'
+}
`,10),e=[p];function t(C,c,r,y,A,i){return a(),n("div",null,e)}const d=s(o,[["render",t]]);export{F as __pageData,d as default}; diff --git a/assets/grants_password.md.94ac36b5.lean.js b/assets/grants_password.md.94ac36b5.lean.js new file mode 100644 index 00000000..bd38b179 --- /dev/null +++ b/assets/grants_password.md.94ac36b5.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as n,O as l}from"./chunks/framework.2958c35d.js";const F=JSON.parse('{"title":"Password Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/password.md","filePath":"grants/password.md"}'),o={name:"grants/password.md"},p=l("",10),e=[p];function t(C,c,r,y,A,i){return a(),n("div",null,e)}const d=s(o,[["render",t]]);export{F as __pageData,d as default}; diff --git a/assets/grants_refresh_token.md.cdff34f8.js b/assets/grants_refresh_token.md.cdff34f8.js new file mode 100644 index 00000000..9b46b1e7 --- /dev/null +++ b/assets/grants_refresh_token.md.cdff34f8.js @@ -0,0 +1,34 @@ +import{_ as s,o as n,c as a,O as l}from"./chunks/framework.2958c35d.js";const F=JSON.parse('{"title":"Refresh Token Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/refresh_token.md","filePath":"grants/refresh_token.md"}'),o={name:"grants/refresh_token.md"},e=l(`

Refresh Token Grant

Access tokens eventually expire. The refresh token grant enables the client to obtain a new access_token from an existing refresh_token.

Flow

A complete refresh token request will include the following parameters:

  • grant_type must be set to refresh_token
  • client_id is the client identifier you received when you first created the application
  • client_secret if the client is confidential (has a secret), this must be provided
  • refresh_token must be the signed token previously issued to the client
  • scope (optional) the requested scope must not include any additional scopes that were not previously issued to the original token
View sample refresh_token request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=refresh_token
+&refresh_token=xxxxxxxxx
+&client_id=xxxxxxxxx
+&client_secret=xxxxxxxxx
+&scope="contacts.read contacts.write"
http
POST /token HTTP/1.1
+Host: example.com
+Authorization: Basic Y4NmE4MzFhZGFkNzU2YWRhN
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=refresh_token
+&refresh_token=xxxxxxxxx
+&scope="contacts.read contacts.write"

The authorization server will respond with the following response

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and is used to authenticate into the resource server
  • refresh_token is a JWT signed token and can be used in with the refresh grant
  • scope is a space delimited list of scopes the token has access to
View sample refresh_token response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1MTJhYjlhNC1jNzg2LTQ4YTYtOGFkNi05NGM1M2E4ZGM2NTEiLCJleHAiOjE2MDE3NjcyMTIsIm5iZiI6MTYwMTc2MzYxMiwiaWF0IjoxNjAxNzYzNjEyLCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGNsaWVudCIsInNjb3BlIjoiIn0.PO4eKSDVsFuKvebEXndWbZsprgzjkzEfHI7cl4N0YpM',
+  refresh_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIzNTYxNWYyZi0xM2ZhLTQ3MzEtODNhMS05ZTM0NTU2YWIzOTAiLCJhY2Nlc3NfdG9rZW5faWQiOiJuZXcgdG9rZW4iLCJyZWZyZXNoX3Rva2VuX2lkIjoidGhpcy1pcy1teS1zdXBlci1zZWNyZXQtcmVmcmVzaC10b2tlbiIsInNjb3BlIjoiIiwidXNlcl9pZCI6IjUxMmFiOWE0LWM3ODYtNDhhNi04YWQ2LTk0YzUzYThkYzY1MSIsImV4cGlyZV90aW1lIjoxNjAxNzY3MjEyLCJpYXQiOjE2MDE3NjM2MTF9.du4KfAzelSA8hzBaqGlrSvPtH-BxOcoUBXW4HS3pJkM',
+  scope: 'contacts.read contacts.write'
+}

Revocation

Refresh tokens are only valid for a single use. In addition, they can be explicitly revoked on a server that supports RFC7009 “OAuth 2.0 Token Revocation”.

A refresh token revocation request will include the following parameters:

  • token is the signed token previously issued to the client
  • token_type_hint (optional) should be set to refresh_token
View sample revoke refresh_token request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+token_type_hint=refresh_token
+&refresh_token=xxxxxxxxx

The authorization server will respond with the following response

View sample revoke refresh_token response
http
HTTP/1.1 200 OK
+Cache-Control: no-store
+Pragma: no-cache
`,16),p=[e];function t(r,c,C,y,i,A){return n(),a("div",null,p)}const h=s(o,[["render",t]]);export{F as __pageData,h as default}; diff --git a/assets/grants_refresh_token.md.cdff34f8.lean.js b/assets/grants_refresh_token.md.cdff34f8.lean.js new file mode 100644 index 00000000..fb8c25c8 --- /dev/null +++ b/assets/grants_refresh_token.md.cdff34f8.lean.js @@ -0,0 +1 @@ +import{_ as s,o as n,c as a,O as l}from"./chunks/framework.2958c35d.js";const F=JSON.parse('{"title":"Refresh Token Grant","description":"","frontmatter":{},"headers":[],"relativePath":"grants/refresh_token.md","filePath":"grants/refresh_token.md"}'),o={name:"grants/refresh_token.md"},e=l("",16),p=[e];function t(r,c,C,y,i,A){return n(),a("div",null,p)}const h=s(o,[["render",t]]);export{F as __pageData,h as default}; diff --git a/assets/index.md.3fa01efd.js b/assets/index.md.3fa01efd.js new file mode 100644 index 00000000..e4e4c1d2 --- /dev/null +++ b/assets/index.md.3fa01efd.js @@ -0,0 +1 @@ +import{_ as e,o as r,c as t,O as a}from"./chunks/framework.2958c35d.js";const _=JSON.parse('{"title":"TypeScript OAuth2.0 Server","description":"","frontmatter":{},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),o={name:"index.md"},i=a('

TypeScript OAuth2.0 Server

🇺🇦 Support Ukraine 🇺🇦

@jmondi/oauth2-server is a standards compliant implementation of an OAuth 2.0 authorization server for Node, written in TypeScript.

Requires node >= 16

Out of the box it supports the following grants:

The following RFCs are implemented:

',8),n=[i];function l(s,h,p,c,f,d){return r(),t("div",null,n)}const g=e(o,[["render",l]]);export{_ as __pageData,g as default}; diff --git a/assets/index.md.3fa01efd.lean.js b/assets/index.md.3fa01efd.lean.js new file mode 100644 index 00000000..5b0cad4d --- /dev/null +++ b/assets/index.md.3fa01efd.lean.js @@ -0,0 +1 @@ +import{_ as e,o as r,c as t,O as a}from"./chunks/framework.2958c35d.js";const _=JSON.parse('{"title":"TypeScript OAuth2.0 Server","description":"","frontmatter":{},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),o={name:"index.md"},i=a("",8),n=[i];function l(s,h,p,c,f,d){return r(),t("div",null,n)}const g=e(o,[["render",l]]);export{_ as __pageData,g as default}; diff --git a/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 b/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 new file mode 100644 index 00000000..2a687296 Binary files /dev/null and b/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 differ diff --git a/assets/inter-italic-cyrillic.ea42a392.woff2 b/assets/inter-italic-cyrillic.ea42a392.woff2 new file mode 100644 index 00000000..f6403515 Binary files /dev/null and b/assets/inter-italic-cyrillic.ea42a392.woff2 differ diff --git a/assets/inter-italic-greek-ext.4fbe9427.woff2 b/assets/inter-italic-greek-ext.4fbe9427.woff2 new file mode 100644 index 00000000..00218960 Binary files /dev/null and b/assets/inter-italic-greek-ext.4fbe9427.woff2 differ diff --git a/assets/inter-italic-greek.8f4463c4.woff2 b/assets/inter-italic-greek.8f4463c4.woff2 new file mode 100644 index 00000000..71c265f8 Binary files /dev/null and b/assets/inter-italic-greek.8f4463c4.woff2 differ diff --git a/assets/inter-italic-latin-ext.bd8920cc.woff2 b/assets/inter-italic-latin-ext.bd8920cc.woff2 new file mode 100644 index 00000000..9c1b9440 Binary files /dev/null and b/assets/inter-italic-latin-ext.bd8920cc.woff2 differ diff --git a/assets/inter-italic-latin.bd3b6f56.woff2 b/assets/inter-italic-latin.bd3b6f56.woff2 new file mode 100644 index 00000000..01fcf207 Binary files /dev/null and b/assets/inter-italic-latin.bd3b6f56.woff2 differ diff --git a/assets/inter-italic-vietnamese.6ce511fb.woff2 b/assets/inter-italic-vietnamese.6ce511fb.woff2 new file mode 100644 index 00000000..e4f788ee Binary files /dev/null and b/assets/inter-italic-vietnamese.6ce511fb.woff2 differ diff --git a/assets/inter-roman-cyrillic-ext.e75737ce.woff2 b/assets/inter-roman-cyrillic-ext.e75737ce.woff2 new file mode 100644 index 00000000..28593ccb Binary files /dev/null and b/assets/inter-roman-cyrillic-ext.e75737ce.woff2 differ diff --git a/assets/inter-roman-cyrillic.5f2c6c8c.woff2 b/assets/inter-roman-cyrillic.5f2c6c8c.woff2 new file mode 100644 index 00000000..a20adc16 Binary files /dev/null and b/assets/inter-roman-cyrillic.5f2c6c8c.woff2 differ diff --git a/assets/inter-roman-greek-ext.ab0619bc.woff2 b/assets/inter-roman-greek-ext.ab0619bc.woff2 new file mode 100644 index 00000000..e3b0be76 Binary files /dev/null and b/assets/inter-roman-greek-ext.ab0619bc.woff2 differ diff --git a/assets/inter-roman-greek.d5a6d92a.woff2 b/assets/inter-roman-greek.d5a6d92a.woff2 new file mode 100644 index 00000000..f790e047 Binary files /dev/null and b/assets/inter-roman-greek.d5a6d92a.woff2 differ diff --git a/assets/inter-roman-latin-ext.0030eebd.woff2 b/assets/inter-roman-latin-ext.0030eebd.woff2 new file mode 100644 index 00000000..715bd903 Binary files /dev/null and b/assets/inter-roman-latin-ext.0030eebd.woff2 differ diff --git a/assets/inter-roman-latin.2ed14f66.woff2 b/assets/inter-roman-latin.2ed14f66.woff2 new file mode 100644 index 00000000..a540b7af Binary files /dev/null and b/assets/inter-roman-latin.2ed14f66.woff2 differ diff --git a/assets/inter-roman-vietnamese.14ce25a6.woff2 b/assets/inter-roman-vietnamese.14ce25a6.woff2 new file mode 100644 index 00000000..5a9f9cb9 Binary files /dev/null and b/assets/inter-roman-vietnamese.14ce25a6.woff2 differ diff --git a/assets/migration_v2_to_v3.md.a4bad7c8.js b/assets/migration_v2_to_v3.md.a4bad7c8.js new file mode 100644 index 00000000..03cf072c --- /dev/null +++ b/assets/migration_v2_to_v3.md.a4bad7c8.js @@ -0,0 +1,28 @@ +import{_ as s,o as a,c as n,O as o}from"./chunks/framework.2958c35d.js";const h=JSON.parse('{"title":"Migrating from v2 to v3","description":"","frontmatter":{},"headers":[],"relativePath":"migration/v2_to_v3.md","filePath":"migration/v2_to_v3.md"}'),e={name:"migration/v2_to_v3.md"},t=o(`

Migrating from v2 to v3

Upgrade Time Estimate: ESM? 10 minutes; no-ESM? Varies

This package is now pure ESM

The package is now entirely ESM (ECMAScript Modules). More details about this change can be found in Sindre Sorhus's writeup.

AuthorizationServer Updates

In v2.x, AuthorizationServer constructor required all repositories. In v3.x, it has been simplified.

Before (v2.x):

typescript
const authorizationServer = new AuthorizationServer(
+  authCodeRepository,
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  userRepository,
+  jwtService,
+  {
+    requiresS256: false, 
+    tokenCID: "name",
+  }
+);

After (v3.x):

typescript
const authorizationServer = new AuthorizationServer(
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  new JwtService("secret-key"),
+  {
+    requiresS256: true,  
+    tokenCID: "id",
+  }
+);

Enabling Grants

In v3, enableGrantType has been updated for the "authorization_code" and "password" grants.

Authorization Code Grant

AuthorizationCodeGrant now requires a AuthorizationCodeRepository and a UserRepository.

Before (v2.x):

typescript
authorizationServer.enableGrantType("authorization_code");

After (v3.x):

typescript
authorizationServer.enableGrantType({
+  grant: "authorization_code",
+  userRepository, 
+  authorizationCodeRepository,
+});

Password Grant

PasswordGrant now requires a UserRepository.

Before (v2.x):

typescript
authorizationServer.enableGrantType("password");

After (v3.x):

typescript
authorizationServer.enableGrantType({
+  grant: "password",
+  userRepository, 
+});

AuthorizationServerOptions Default Configuration Updates

The default options for AuthorizationServer have been modified to better align with the OAuth 2.0 specification:

Optionv2.x Valuev3.x Value
requiresS256falsetrue
tokenCID"name""id"

Removed setOptions Method

The undocumented, public method setOptions has been removed in v3. Options can be set during AuthorizationServer initialization.

generateRandomToken Function Fix

A bug in the generateRandomToken function has been fixed in v3.x.

`,32),p=[t];function l(r,i,c,D,y,d){return a(),n("div",null,p)}const A=s(e,[["render",l]]);export{h as __pageData,A as default}; diff --git a/assets/migration_v2_to_v3.md.a4bad7c8.lean.js b/assets/migration_v2_to_v3.md.a4bad7c8.lean.js new file mode 100644 index 00000000..eee5b1a4 --- /dev/null +++ b/assets/migration_v2_to_v3.md.a4bad7c8.lean.js @@ -0,0 +1 @@ +import{_ as s,o as a,c as n,O as o}from"./chunks/framework.2958c35d.js";const h=JSON.parse('{"title":"Migrating from v2 to v3","description":"","frontmatter":{},"headers":[],"relativePath":"migration/v2_to_v3.md","filePath":"migration/v2_to_v3.md"}'),e={name:"migration/v2_to_v3.md"},t=o("",32),p=[t];function l(r,i,c,D,y,d){return a(),n("div",null,p)}const A=s(e,[["render",l]]);export{h as __pageData,A as default}; diff --git a/assets/repositories_index.md.21008022.js b/assets/repositories_index.md.21008022.js new file mode 100644 index 00000000..cc5c9680 --- /dev/null +++ b/assets/repositories_index.md.21008022.js @@ -0,0 +1,94 @@ +import{_ as s,o as n,c as a,O as l}from"./chunks/framework.2958c35d.js";const A=JSON.parse('{"title":"Repository Interfaces","description":"","frontmatter":{},"headers":[],"relativePath":"repositories/index.md","filePath":"repositories/index.md"}'),o={name:"repositories/index.md"},e=l(`

Repository Interfaces

Auth Code Repository

OAuthAuthCodeRepository interface is utilized for managing OAuth authorization codes. It contains methods for retrieving an authorization code entity by its identifier, issuing a new authorization code, persisting an authorization code in the storage, checking if an authorization code has been revoked, and revoking an authorization code.

typescript
interface OAuthAuthCodeRepository {
+
+  // Fetch auth code entity from storage by code
+  getByIdentifier(authCodeCode: string): Promise<OAuthAuthCode>;
+
+  // An async call that should return an OAuthAuthCode that has not been 
+  // persisted to storage yet.
+  issueAuthCode(
+    client: OAuthClient, 
+    user: OAuthUser | undefined, 
+    scopes: OAuthScope[]
+  ): OAuthAuthCode | Promise<OAuthAuthCode>;
+
+  // An async call that should persist an OAuthAuthCode into your storage.
+  persist(authCode: OAuthAuthCode): Promise<void>;
+
+  // This async method is called when an auth code is validated by the 
+  // authorization server. Return \`true\` if the auth code has been 
+  // manually revoked. If the code is still valid return \`false\`
+  isRevoked(authCodeCode: string): Promise<boolean>;
+
+  revoke(authCodeCode: string): Promise<void>;
+}

Client Repository

OAuthClientRepository interface is used for managing OAuth clients. It includes methods for fetching a client entity from storage by the client ID and for validating the client using the grant type and client secret.

typescript
interface OAuthClientRepository {
+  // Fetch client entity from storage by client_id
+  getByIdentifier(clientId: string): Promise<OAuthClient>;
+
+  // check the grant type and secret against the client
+  isClientValid(
+    grantType: GrantIdentifier, 
+    client: OAuthClient, 
+    clientSecret?: string
+  ): Promise<boolean>;
+}

Scope Repository

The OAuthScopeRepository interface handles scope management. It defines methods for finding all scopes by their names and for finalizing the scopes. In the finalization, additional scopes can be added or removed after they've been validated against the client scopes.

typescript
interface OAuthScopeRepository {
+  // Find all scopes by scope names
+  getAllByIdentifiers(scopeNames: string[]): Promise<OAuthScope[]>;
+
+  // Scopes have already been validated against the client, if you arent 
+  // doing anything fancy with scopes, you can just \`return scopes\`,
+  // Otherwise, now is your chance to add or remove any final scopes 
+  // after they have already been validated against the client scopes
+  finalize(
+    scopes: OAuthScope[],
+    identifier: GrantIdentifier,
+    client: OAuthClient,
+    user_id?: string,
+  ): Promise<OAuthScope[]>;
+}

Token Repository

OAuthTokenRepository interface manages OAuth tokens. It contains methods for issuing a new token, persisting a token in the storage, issuing a refresh token, revoking tokens, and fetching a refresh token entity by the refresh token.

typescript
interface OAuthTokenRepository {
+  // An async call that should return an OAuthToken that has not been 
+  // persisted to storage yet.
+  issueToken(
+    client: OAuthClient,
+    scopes: OAuthScope[],
+    user?: OAuthUser
+  ): Promise<OAuthToken>;
+
+  // An async call that should persist an OAuthToken into your storage.
+  persist(accessToken: OAuthToken): Promise<void>;
+
+  // An async call that enhances an already-persisted OAuthToken with
+  // refresh token fields.
+  issueRefreshToken(
+    accessToken: OAuthToken,
+    client: OAuthClient,
+  ): Promise<OAuthToken>
+
+  // This async method is called when a refresh token is used to reissue 
+  // an access token. The original access token is revoked, and a new
+  // access token is issued.
+  revoke(accessToken: OAuthToken): Promise<void>;
+
+  // This async method, if implemented, will be called by the authorization
+  // code grant if the original authorization code is reused.
+  // See https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2 for why.
+  revokeDescendantsOf?(authCodeId: string): Promise<void>;
+
+  // This async method is called when an access token is validated by the 
+  // authorization server. Return \`true\` if the access token has been 
+  // manually revoked. If the token is still valid return \`false\`
+  isRefreshTokenRevoked(refreshToken: OAuthToken): Promise<boolean>;
+
+  // Fetch refresh token entity from storage by refresh token
+  getByRefreshToken(refreshTokenToken: string): Promise<OAuthToken>;
+}

User Repository

The OAuthUserRepository interface handles user management. It defines methods for fetching a user entity from storage by their credentials and optional grant type and client. This may involve validating the user's credentials.

typescript
interface OAuthUserRepository {
+
+  // Fetch user entity from storage by identifier. A provided password may 
+  // be used to validate the users credentials. Grant type and client are provided
+  // for additional checks if desired
+  getUserByCredentials(
+    identifier: string,
+    password?: string,
+    grantType?: GrantIdentifier,
+    client?: OAuthClient,
+  ): Promise<OAuthUser | undefined>;
+}
`,16),p=[e];function t(c,r,i,y,F,D){return n(),a("div",null,p)}const h=s(o,[["render",t]]);export{A as __pageData,h as default}; diff --git a/assets/repositories_index.md.21008022.lean.js b/assets/repositories_index.md.21008022.lean.js new file mode 100644 index 00000000..21f62ea8 --- /dev/null +++ b/assets/repositories_index.md.21008022.lean.js @@ -0,0 +1 @@ +import{_ as s,o as n,c as a,O as l}from"./chunks/framework.2958c35d.js";const A=JSON.parse('{"title":"Repository Interfaces","description":"","frontmatter":{},"headers":[],"relativePath":"repositories/index.md","filePath":"repositories/index.md"}'),o={name:"repositories/index.md"},e=l("",16),p=[e];function t(c,r,i,y,F,D){return n(),a("div",null,p)}const h=s(o,[["render",t]]);export{A as __pageData,h as default}; diff --git a/assets/sources_index.md.6a0f1688.js b/assets/sources_index.md.6a0f1688.js new file mode 100644 index 00000000..bba91a6c --- /dev/null +++ b/assets/sources_index.md.6a0f1688.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as r,O as o}from"./chunks/framework.2958c35d.js";const m=JSON.parse('{"title":"Sources","description":"","frontmatter":{},"headers":[],"relativePath":"sources/index.md","filePath":"sources/index.md"}'),s={name:"sources/index.md"},a=o('

Sources

This project was influenced by the PHP League OAuth2 Server and shares a lot of the same ideas.

https://github.com/thephpleague/oauth2-server

https://tools.ietf.org/html/rfc6749#section-4.4

https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/

https://www.oauth.com/oauth2-servers/access-tokens/access-token-response/

https://tools.ietf.org/html/rfc6749#section-4.1

https://tools.ietf.org/html/rfc7009

https://tools.ietf.org/html/rfc7636

https://www.oauth.com/oauth2-servers/pkce/

https://www.oauth.com/oauth2-servers/pkce/authorization-request/

',11),h=[a];function c(n,p,l,f,i,u){return t(),r("div",null,h)}const d=e(s,[["render",c]]);export{m as __pageData,d as default}; diff --git a/assets/sources_index.md.6a0f1688.lean.js b/assets/sources_index.md.6a0f1688.lean.js new file mode 100644 index 00000000..bea28c95 --- /dev/null +++ b/assets/sources_index.md.6a0f1688.lean.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as r,O as o}from"./chunks/framework.2958c35d.js";const m=JSON.parse('{"title":"Sources","description":"","frontmatter":{},"headers":[],"relativePath":"sources/index.md","filePath":"sources/index.md"}'),s={name:"sources/index.md"},a=o("",11),h=[a];function c(n,p,l,f,i,u){return t(),r("div",null,h)}const d=e(s,[["render",c]]);export{m as __pageData,d as default}; diff --git a/assets/style.f4c2803b.css b/assets/style.f4c2803b.css new file mode 100644 index 00000000..979c1980 --- /dev/null +++ b/assets/style.f4c2803b.css @@ -0,0 +1 @@ +@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/ts-oauth2-server/assets/inter-roman-cyrillic.5f2c6c8c.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/ts-oauth2-server/assets/inter-roman-cyrillic-ext.e75737ce.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/ts-oauth2-server/assets/inter-roman-greek.d5a6d92a.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/ts-oauth2-server/assets/inter-roman-greek-ext.ab0619bc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/ts-oauth2-server/assets/inter-roman-latin.2ed14f66.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/ts-oauth2-server/assets/inter-roman-latin-ext.0030eebd.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/ts-oauth2-server/assets/inter-roman-vietnamese.14ce25a6.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/ts-oauth2-server/assets/inter-italic-cyrillic.ea42a392.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/ts-oauth2-server/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/ts-oauth2-server/assets/inter-italic-greek.8f4463c4.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/ts-oauth2-server/assets/inter-italic-greek-ext.4fbe9427.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/ts-oauth2-server/assets/inter-italic-latin.bd3b6f56.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/ts-oauth2-server/assets/inter-italic-latin-ext.bd8920cc.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/ts-oauth2-server/assets/inter-italic-vietnamese.6ce511fb.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Chinese Quotes;src:local("PingFang SC Regular"),local("PingFang SC"),local("SimHei"),local("Source Han Sans SC");unicode-range:U+2018,U+2019,U+201C,U+201D}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-gray: #8e8e93;--vp-c-text-light-1: rgba(60, 60, 67);--vp-c-text-light-2: rgba(60, 60, 67, .75);--vp-c-text-light-3: rgba(60, 60, 67, .33);--vp-c-text-dark-1: rgba(255, 255, 245, .86);--vp-c-text-dark-2: rgba(235, 235, 245, .6);--vp-c-text-dark-3: rgba(235, 235, 245, .38);--vp-c-green: #10b981;--vp-c-green-light: #34d399;--vp-c-green-lighter: #6ee7b7;--vp-c-green-dark: #059669;--vp-c-green-darker: #047857;--vp-c-green-dimm-1: rgba(16, 185, 129, .05);--vp-c-green-dimm-2: rgba(16, 185, 129, .2);--vp-c-green-dimm-3: rgba(16, 185, 129, .5);--vp-c-yellow: #d97706;--vp-c-yellow-light: #f59e0b;--vp-c-yellow-lighter: #fbbf24;--vp-c-yellow-dark: #b45309;--vp-c-yellow-darker: #92400e;--vp-c-yellow-dimm-1: rgba(234, 179, 8, .05);--vp-c-yellow-dimm-2: rgba(234, 179, 8, .2);--vp-c-yellow-dimm-3: rgba(234, 179, 8, .5);--vp-c-red: #f43f5e;--vp-c-red-light: #fb7185;--vp-c-red-lighter: #fda4af;--vp-c-red-dark: #e11d48;--vp-c-red-darker: #be123c;--vp-c-red-dimm-1: rgba(244, 63, 94, .05);--vp-c-red-dimm-2: rgba(244, 63, 94, .2);--vp-c-red-dimm-3: rgba(244, 63, 94, .5);--vp-c-sponsor: #db2777}:root{--vp-c-bg: #ffffff;--vp-c-bg-elv: #ffffff;--vp-c-bg-elv-up: #ffffff;--vp-c-bg-elv-down: #f6f6f7;--vp-c-bg-elv-mute: #f6f6f7;--vp-c-bg-soft: #f6f6f7;--vp-c-bg-soft-up: #f9f9fa;--vp-c-bg-soft-down: #e3e3e5;--vp-c-bg-soft-mute: #e3e3e5;--vp-c-bg-alt: #f6f6f7;--vp-c-border: rgba(60, 60, 67, .29);--vp-c-divider: rgba(60, 60, 67, .12);--vp-c-gutter: rgba(60, 60, 67, .12);--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white);--vp-c-text-1: var(--vp-c-text-light-1);--vp-c-text-2: var(--vp-c-text-light-2);--vp-c-text-3: var(--vp-c-text-light-3);--vp-c-text-inverse-1: var(--vp-c-text-dark-1);--vp-c-text-inverse-2: var(--vp-c-text-dark-2);--vp-c-text-inverse-3: var(--vp-c-text-dark-3);--vp-c-text-code: #476582;--vp-c-brand: var(--vp-c-green);--vp-c-brand-light: var(--vp-c-green-light);--vp-c-brand-lighter: var(--vp-c-green-lighter);--vp-c-brand-dark: var(--vp-c-green-dark);--vp-c-brand-darker: var(--vp-c-green-darker);--vp-c-mute: #f6f6f7;--vp-c-mute-light: #f9f9fc;--vp-c-mute-lighter: #ffffff;--vp-c-mute-dark: #e3e3e5;--vp-c-mute-darker: #d7d7d9}.dark{--vp-c-bg: #1e1e20;--vp-c-bg-elv: #252529;--vp-c-bg-elv-up: #313136;--vp-c-bg-elv-down: #1e1e20;--vp-c-bg-elv-mute: #313136;--vp-c-bg-soft: #252529;--vp-c-bg-soft-up: #313136;--vp-c-bg-soft-down: #1e1e20;--vp-c-bg-soft-mute: #313136;--vp-c-bg-alt: #161618;--vp-c-border: rgba(82, 82, 89, .68);--vp-c-divider: rgba(82, 82, 89, .32);--vp-c-gutter: #000000;--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black);--vp-c-text-1: var(--vp-c-text-dark-1);--vp-c-text-2: var(--vp-c-text-dark-2);--vp-c-text-3: var(--vp-c-text-dark-3);--vp-c-text-inverse-1: var(--vp-c-text-light-1);--vp-c-text-inverse-2: var(--vp-c-text-light-2);--vp-c-text-inverse-3: var(--vp-c-text-light-3);--vp-c-text-code: #c9def1;--vp-c-mute: #313136;--vp-c-mute-light: #3a3a3c;--vp-c-mute-lighter: #505053;--vp-c-mute-dark: #2c2c30;--vp-c-mute-darker: #252529}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-local-nav: 10;--vp-z-index-nav: 20;--vp-z-index-layout-top: 30;--vp-z-index-backdrop: 40;--vp-z-index-sidebar: 50;--vp-z-index-footer: 60}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E")}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-c-code-dimm: var(--vp-c-text-dark-3);--vp-code-block-color: var(--vp-c-text-dark-1);--vp-code-block-bg: #292b30;--vp-code-block-bg-light: #1e1e20;--vp-code-block-divider-color: #000000;--vp-code-line-highlight-color: rgba(0, 0, 0, .5);--vp-code-line-number-color: var(--vp-c-code-dimm);--vp-code-line-diff-add-color: var(--vp-c-green-dimm-2);--vp-code-line-diff-add-symbol-color: var(--vp-c-green);--vp-code-line-diff-remove-color: var(--vp-c-red-dimm-2);--vp-code-line-diff-remove-symbol-color: var(--vp-c-red);--vp-code-line-warning-color: var(--vp-c-yellow-dimm-2);--vp-code-line-error-color: var(--vp-c-red-dimm-2);--vp-code-copy-code-border-color: transparent;--vp-code-copy-code-bg: var(--vp-code-block-bg-light);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-code-block-bg-light);--vp-code-copy-code-active-text: var(--vp-c-text-dark-2);--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-dark-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-dark-1);--vp-code-tab-active-text-color: var(--vp-c-text-dark-1);--vp-code-tab-active-bar-color: var(--vp-c-brand)}.dark{--vp-code-block-bg: #161618}:root:not(.dark) .vp-adaptive-theme{--vp-c-code-dimm: var(--vp-c-text-2);--vp-code-block-color: var(--vp-c-text-1);--vp-code-block-bg: #f8f8f8;--vp-code-block-divider-color: var(--vp-c-divider);--vp-code-line-highlight-color: #ececec;--vp-code-line-number-color: var(--vp-c-code-dimm);--vp-code-copy-code-bg: #e2e2e2;--vp-code-copy-code-hover-bg: #dcdcdc;--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-tab-divider: var(--vp-c-divider);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1)}:root{--vp-button-brand-border: var(--vp-c-brand-lighter);--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand);--vp-button-brand-hover-border: var(--vp-c-brand-lighter);--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-dark);--vp-button-brand-active-border: var(--vp-c-brand-lighter);--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-darker);--vp-button-alt-border: var(--vp-c-border);--vp-button-alt-text: var(--vp-c-neutral);--vp-button-alt-bg: var(--vp-c-mute);--vp-button-alt-hover-border: var(--vp-c-border);--vp-button-alt-hover-text: var(--vp-c-neutral);--vp-button-alt-hover-bg: var(--vp-c-mute-dark);--vp-button-alt-active-border: var(--vp-c-border);--vp-button-alt-active-text: var(--vp-c-neutral);--vp-button-alt-active-bg: var(--vp-c-mute-darker);--vp-button-sponsor-border: var(--vp-c-gray-light-3);--vp-button-sponsor-text: var(--vp-c-text-light-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}.dark{--vp-button-sponsor-border: var(--vp-c-gray-dark-1);--vp-button-sponsor-text: var(--vp-c-text-dark-2)}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: var(--vp-c-border);--vp-custom-block-info-text: var(--vp-c-text-2);--vp-custom-block-info-bg: var(--vp-c-bg-soft-up);--vp-custom-block-info-code-bg: var(--vp-c-bg-soft);--vp-custom-block-tip-border: var(--vp-c-green);--vp-custom-block-tip-text: var(--vp-c-green-dark);--vp-custom-block-tip-bg: var(--vp-c-bg-soft-up);--vp-custom-block-tip-code-bg: var(--vp-c-bg-soft);--vp-custom-block-warning-border: var(--vp-c-yellow);--vp-custom-block-warning-text: var(--vp-c-yellow);--vp-custom-block-warning-bg: var(--vp-c-bg-soft-up);--vp-custom-block-warning-code-bg: var(--vp-c-bg-soft);--vp-custom-block-danger-border: var(--vp-c-red);--vp-custom-block-danger-text: var(--vp-c-red);--vp-custom-block-danger-bg: var(--vp-c-bg-soft-up);--vp-custom-block-danger-code-bg: var(--vp-c-bg-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-details-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-hover-border-color: var(--vp-c-gray);--vp-input-switch-bg-color: var(--vp-c-mute)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg)}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: var(--vp-c-border);--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-bg-soft-up);--vp-badge-tip-border: var(--vp-c-green-dark);--vp-badge-tip-text: var(--vp-c-green);--vp-badge-tip-bg: var(--vp-c-green-dimm-1);--vp-badge-warning-border: var(--vp-c-yellow-dark);--vp-badge-warning-text: var(--vp-c-yellow);--vp-badge-warning-bg: var(--vp-c-yellow-dimm-1);--vp-badge-danger-border: var(--vp-c-red-dark);--vp-badge-danger-text: var(--vp-c-red);--vp-badge-danger-bg: var(--vp-c-red-dimm-1)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand);--vp-local-search-highlight-bg: var(--vp-c-green-lighter);--vp-local-search-highlight-text: var(--vp-c-black)}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);direction:ltr;font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600}.custom-block a:hover{text-decoration:underline}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.dark .vp-code-light{display:none}html:not(.dark) .vp-code-dark{display:none}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden}.vp-code-group .tabs:after{position:absolute;right:0;bottom:0;left:0;height:1px;background-color:var(--vp-code-tab-divider);content:""}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:absolute;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:10;height:1px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-]{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active{display:block}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{float:left;margin-left:-.87em;padding-right:.23em;font-weight:500;user-select:none;opacity:0;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand);text-decoration-style:dotted;transition:color .25s}.vp-doc a:hover{text-decoration:underline}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block a{color:inherit;font-weight:600}.vp-doc .custom-block a:hover{text-decoration:underline}.vp-doc .custom-block code{font-size:var(--vp-custom-block-code-font-size);font-weight:700;color:inherit}.vp-doc .custom-block div[class*=language-]{margin:8px 0}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;color:var(--vp-c-text-code);background-color:var(--vp-c-mute);transition:color .5s,background-color .5s}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc a>code{color:var(--vp-c-brand);transition:color .25s}.vp-doc a:hover>code{color:var(--vp-c-brand-dark)}.vp-doc div[class*=language-]{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-]{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;left:-65px;display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;width:64px;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:"Copied"}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-c-code-dimm);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin-bottom:4px;text-align:center;letter-spacing:1px;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-bg-soft-down)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge[data-v-9b69adbb]{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:10px;padding:0 8px;line-height:18px;font-size:12px;font-weight:600;transform:translateY(-2px)}h1 .VPBadge[data-v-9b69adbb],h2 .VPBadge[data-v-9b69adbb],h3 .VPBadge[data-v-9b69adbb],h4 .VPBadge[data-v-9b69adbb],h5 .VPBadge[data-v-9b69adbb],h6 .VPBadge[data-v-9b69adbb]{vertical-align:top}h2 .VPBadge[data-v-9b69adbb]{border-radius:11px;line-height:20px}.VPBadge.info[data-v-9b69adbb]{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip[data-v-9b69adbb]{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning[data-v-9b69adbb]{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger[data-v-9b69adbb]{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPSkipLink[data-v-a9cecaf0]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-a9cecaf0]:focus{height:auto;width:auto;clip:auto;clip-path:none}.dark .VPSkipLink[data-v-a9cecaf0]{color:var(--vp-c-green)}@media (min-width: 1280px){.VPSkipLink[data-v-a9cecaf0]{top:14px;left:16px}}.VPBackdrop[data-v-2b17fbdf]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-2b17fbdf],.VPBackdrop.fade-leave-to[data-v-2b17fbdf]{opacity:0}.VPBackdrop.fade-leave-active[data-v-2b17fbdf]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-2b17fbdf]{display:none}}html:not(.dark) .VPImage.dark[data-v-db57fb8d]{display:none}.dark .VPImage.light[data-v-db57fb8d]{display:none}.title[data-v-a11742b6]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-a11742b6]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-a11742b6]{border-bottom-color:var(--vp-c-divider)}}[data-v-a11742b6] .logo{margin-right:8px;height:24px}/*! @docsearch/css 3.4.0 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.DocSearch{--docsearch-primary-color: var(--vp-c-brand);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark .DocSearch{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-bg-soft-mute);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:1px;letter-spacing:-12px;color:transparent}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:var(--vp-meta-key);font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-bg-soft-mute)}.DocSearch-Screen-Icon>svg{margin:auto}.icon[data-v-99223c31]{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;fill:var(--vp-c-text-3);transition:fill .25s;flex-shrink:0}.VPNavBarMenuLink[data-v-60fab7df]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-60fab7df],.VPNavBarMenuLink[data-v-60fab7df]:hover{color:var(--vp-c-brand)}.VPMenuGroup+.VPMenuLink[data-v-c494398b]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-c494398b]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-c494398b]:hover{color:var(--vp-c-brand);background-color:var(--vp-c-bg-elv-mute)}.link.active[data-v-c494398b]{color:var(--vp-c-brand)}.VPMenuGroup[data-v-b86dd50d]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-b86dd50d]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-b86dd50d]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-b86dd50d]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-eba8cec3]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-eba8cec3] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-eba8cec3] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-eba8cec3] .group:last-child{padding-bottom:0}.VPMenu[data-v-eba8cec3] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-eba8cec3] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-eba8cec3] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-eba8cec3] .action{padding-left:24px}.VPFlyout[data-v-eba080dd]{position:relative}.VPFlyout[data-v-eba080dd]:hover{color:var(--vp-c-brand);transition:color .25s}.VPFlyout:hover .text[data-v-eba080dd]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-eba080dd]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-eba080dd]{color:var(--vp-c-brand)}.VPFlyout.active:hover .text[data-v-eba080dd]{color:var(--vp-c-brand-dark)}.VPFlyout:hover .menu[data-v-eba080dd],.button[aria-expanded=true]+.menu[data-v-eba080dd]{opacity:1;visibility:visible;transform:translateY(0)}.button[data-v-eba080dd]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-eba080dd]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-eba080dd]{margin-right:0;width:16px;height:16px;fill:currentColor}.text-icon[data-v-eba080dd]{margin-left:4px;width:14px;height:14px;fill:currentColor}.icon[data-v-eba080dd]{width:20px;height:20px;fill:currentColor;transition:fill .25s}.menu[data-v-eba080dd]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPNavBarMenu[data-v-1f756838]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-1f756838]{display:flex}}.VPNavBarTranslations[data-v-a02f8de7]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-a02f8de7]{display:flex;align-items:center}}.title[data-v-a02f8de7]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPSwitch[data-v-863a2c7f]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s}.VPSwitch[data-v-863a2c7f]:hover{border-color:var(--vp-input-hover-border-color)}.check[data-v-863a2c7f]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s}.icon[data-v-863a2c7f]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-863a2c7f] svg{position:absolute;top:3px;left:3px;width:12px;height:12px;fill:var(--vp-c-text-2)}.dark .icon[data-v-863a2c7f] svg{fill:var(--vp-c-text-1);transition:opacity .25s}.sun[data-v-0f4f1edf]{opacity:1}.moon[data-v-0f4f1edf],.dark .sun[data-v-0f4f1edf]{opacity:0}.dark .moon[data-v-0f4f1edf]{opacity:1}.dark .VPSwitchAppearance[data-v-0f4f1edf] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-8a490153]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-8a490153]{display:flex;align-items:center}}.VPSocialLink[data-v-363a4685]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-363a4685]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-363a4685]>svg{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-2fb8166f]{display:flex;justify-content:center}.VPNavBarSocialLinks[data-v-ac78dc9e]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-ac78dc9e]{display:flex;align-items:center}}.VPNavBarExtra[data-v-4fdc941c]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-4fdc941c]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-4fdc941c]{display:none}}.trans-title[data-v-4fdc941c]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-4fdc941c],.item.social-links[data-v-4fdc941c]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-4fdc941c]{min-width:176px}.appearance-action[data-v-4fdc941c]{margin-right:-2px}.social-links-list[data-v-4fdc941c]{margin:-4px -8px}.VPNavBarHamburger[data-v-519742d4]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-519742d4]{display:none}}.container[data-v-519742d4]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-519742d4]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-519742d4]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-519742d4]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-519742d4]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-519742d4]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-519742d4]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-519742d4],.VPNavBarHamburger.active:hover .middle[data-v-519742d4],.VPNavBarHamburger.active:hover .bottom[data-v-519742d4]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-519742d4],.middle[data-v-519742d4],.bottom[data-v-519742d4]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-519742d4]{top:0;left:0;transform:translate(0)}.middle[data-v-519742d4]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-519742d4]{top:12px;left:0;transform:translate(4px)}.VPNavBar[data-v-e223f26c]{position:relative;border-bottom:1px solid transparent;padding:0 8px 0 24px;height:var(--vp-nav-height);transition:border-color .5s,background-color .5s;pointer-events:none;white-space:nowrap}.VPNavBar.has-sidebar[data-v-e223f26c]{border-bottom-color:var(--vp-c-gutter)}@media (min-width: 768px){.VPNavBar[data-v-e223f26c]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar[data-v-e223f26c]{border-bottom-color:transparent;padding:0}.VPNavBar.fill[data-v-e223f26c]:not(.has-sidebar){border-bottom-color:var(--vp-c-gutter);background-color:var(--vp-nav-bg-color)}}.container[data-v-e223f26c]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-e223f26c],.container>.content[data-v-e223f26c]{pointer-events:none}.container[data-v-e223f26c] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-e223f26c]{max-width:100%}}.title[data-v-e223f26c]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-e223f26c]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-e223f26c]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-e223f26c]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-e223f26c]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-e223f26c]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-e223f26c]{display:flex;justify-content:flex-end;align-items:center;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .content-body[data-v-e223f26c],.VPNavBar.fill .content-body[data-v-e223f26c]{position:relative;background-color:var(--vp-nav-bg-color)}}@media (max-width: 768px){.content-body[data-v-e223f26c]{column-gap:.5rem}}.menu+.translations[data-v-e223f26c]:before,.menu+.appearance[data-v-e223f26c]:before,.menu+.social-links[data-v-e223f26c]:before,.translations+.appearance[data-v-e223f26c]:before,.appearance+.social-links[data-v-e223f26c]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-e223f26c]:before,.translations+.appearance[data-v-e223f26c]:before{margin-right:16px}.appearance+.social-links[data-v-e223f26c]:before{margin-left:16px}.social-links[data-v-e223f26c]{margin-right:-8px}@media (min-width: 960px){.VPNavBar.has-sidebar .curtain[data-v-e223f26c]{position:absolute;right:0;bottom:-31px;width:calc(100% - var(--vp-sidebar-width));height:32px}.VPNavBar.has-sidebar .curtain[data-v-e223f26c]:before{display:block;width:100%;height:32px;background:linear-gradient(var(--vp-c-bg),transparent 70%);content:""}}@media (min-width: 1440px){.VPNavBar.has-sidebar .curtain[data-v-e223f26c]{width:calc(100% - ((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width)))}}.VPNavScreenMenuLink[data-v-aa70a253]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-aa70a253]:hover{color:var(--vp-c-brand)}.VPNavScreenMenuGroupLink[data-v-f77b192e]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-f77b192e]:hover{color:var(--vp-c-brand)}.VPNavScreenMenuGroupSection[data-v-4975e1ab]{display:block}.title[data-v-4975e1ab]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-fc451118]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-fc451118]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-fc451118]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-fc451118]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-fc451118]{padding-bottom:6px;color:var(--vp-c-brand)}.VPNavScreenMenuGroup.open .button-icon[data-v-fc451118]{transform:rotate(45deg)}.button[data-v-fc451118]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-fc451118]:hover{color:var(--vp-c-brand)}.button-icon[data-v-fc451118]{width:14px;height:14px;fill:var(--vp-c-text-2);transition:fill .5s,transform .25s}.group[data-v-fc451118]:first-child{padding-top:0}.group+.group[data-v-fc451118],.group+.item[data-v-fc451118]{padding-top:4px}.VPNavScreenAppearance[data-v-089a640c]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-089a640c]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenTranslations[data-v-35099923]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-35099923]{height:auto}.title[data-v-35099923]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-35099923]{width:16px;height:16px;fill:currentColor}.icon.lang[data-v-35099923]{margin-right:8px}.icon.chevron[data-v-35099923]{margin-left:4px}.list[data-v-35099923]{padding:4px 0 0 24px}.link[data-v-35099923]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-7f135a4c]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-7f135a4c],.VPNavScreen.fade-leave-active[data-v-7f135a4c]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-7f135a4c],.VPNavScreen.fade-leave-active .container[data-v-7f135a4c]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-7f135a4c],.VPNavScreen.fade-leave-to[data-v-7f135a4c]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-7f135a4c],.VPNavScreen.fade-leave-to .container[data-v-7f135a4c]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-7f135a4c]{display:none}}.container[data-v-7f135a4c]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-7f135a4c],.menu+.appearance[data-v-7f135a4c],.translations+.appearance[data-v-7f135a4c]{margin-top:24px}.menu+.social-links[data-v-7f135a4c]{margin-top:16px}.appearance+.social-links[data-v-7f135a4c]{margin-top:16px}.VPNav[data-v-9f003a64]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-9f003a64]{position:fixed}}.root[data-v-f461fd14]{position:relative;z-index:1}.nested[data-v-f461fd14]{padding-left:13px}.outline-link[data-v-f461fd14]{display:block;line-height:28px;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s;font-weight:500}.outline-link[data-v-f461fd14]:hover,.outline-link.active[data-v-f461fd14]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-f461fd14]{padding-left:13px}.VPLocalNavOutlineDropdown[data-v-57c1b8b6]{padding:12px 20px 11px}.VPLocalNavOutlineDropdown button[data-v-57c1b8b6]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-57c1b8b6]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-57c1b8b6]{color:var(--vp-c-text-1)}.icon[data-v-57c1b8b6]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}[data-v-57c1b8b6] .outline-link{font-size:14px;padding:2px 0}.open>.icon[data-v-57c1b8b6]{transform:rotate(90deg)}.items[data-v-57c1b8b6]{position:absolute;left:20px;right:20px;top:64px;background-color:var(--vp-local-nav-bg-color);padding:4px 10px 16px;border:1px solid var(--vp-c-divider);border-radius:8px;max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}.top-link[data-v-57c1b8b6]{display:block;color:var(--vp-c-brand);font-size:13px;font-weight:500;padding:6px 0;margin:0 13px 10px;border-bottom:1px solid var(--vp-c-divider)}.flyout-enter-active[data-v-57c1b8b6]{transition:all .2s ease-out}.flyout-leave-active[data-v-57c1b8b6]{transition:all .15s ease-in}.flyout-enter-from[data-v-57c1b8b6],.flyout-leave-to[data-v-57c1b8b6]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-8aa06a5b]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color);transition:border-color .5s,background-color .5s}@media (min-width: 960px){.VPLocalNav[data-v-8aa06a5b]{display:none}}.menu[data-v-8aa06a5b]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-8aa06a5b]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-8aa06a5b]{padding:0 32px}}.menu-icon[data-v-8aa06a5b]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPOutlineDropdown[data-v-8aa06a5b]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-8aa06a5b]{padding:12px 32px 11px}}.VPSidebarItem.level-0[data-v-7790c0ef]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-7790c0ef]{padding-bottom:10px}.item[data-v-7790c0ef]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-7790c0ef]{cursor:pointer}.indicator[data-v-7790c0ef]{position:absolute;top:6px;bottom:6px;left:-17px;width:1px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-7790c0ef],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-7790c0ef],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-7790c0ef],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-7790c0ef]{background-color:var(--vp-c-brand)}.link[data-v-7790c0ef]{display:flex;align-items:center;flex-grow:1}.text[data-v-7790c0ef]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-7790c0ef]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-7790c0ef],.VPSidebarItem.level-2 .text[data-v-7790c0ef],.VPSidebarItem.level-3 .text[data-v-7790c0ef],.VPSidebarItem.level-4 .text[data-v-7790c0ef],.VPSidebarItem.level-5 .text[data-v-7790c0ef]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-7790c0ef],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-7790c0ef],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-7790c0ef],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-7790c0ef],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-7790c0ef],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-7790c0ef]{color:var(--vp-c-brand)}.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-7790c0ef],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-7790c0ef],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-7790c0ef],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-7790c0ef],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-7790c0ef],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-7790c0ef]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-7790c0ef],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-7790c0ef],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-7790c0ef],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-7790c0ef],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-7790c0ef],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-7790c0ef]{color:var(--vp-c-brand)}.caret[data-v-7790c0ef]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s}.item:hover .caret[data-v-7790c0ef]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-7790c0ef]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-7790c0ef]{width:18px;height:18px;fill:currentColor;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-7790c0ef]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-7790c0ef],.VPSidebarItem.level-2 .items[data-v-7790c0ef],.VPSidebarItem.level-3 .items[data-v-7790c0ef],.VPSidebarItem.level-4 .items[data-v-7790c0ef],.VPSidebarItem.level-5 .items[data-v-7790c0ef]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-7790c0ef]{display:none}.VPSidebar[data-v-36542528]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-36542528]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-36542528]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-36542528]{z-index:1;padding-top:var(--vp-nav-height);padding-bottom:128px;width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-36542528]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-36542528]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-36542528]{outline:0}.group+.group[data-v-36542528]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-36542528]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPButton[data-v-49324e83]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-49324e83]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-49324e83]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-49324e83]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-49324e83]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-49324e83]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-49324e83]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-49324e83]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-49324e83]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-49324e83]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-49324e83]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-49324e83]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-49324e83]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}.VPHero[data-v-9f53e527]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-9f53e527]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-9f53e527]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-9f53e527]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-9f53e527]{flex-direction:row}}.main[data-v-9f53e527]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-9f53e527]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-9f53e527]{text-align:left}}@media (min-width: 960px){.main[data-v-9f53e527]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-9f53e527]{max-width:592px}}.name[data-v-9f53e527],.text[data-v-9f53e527]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-9f53e527],.VPHero.has-image .text[data-v-9f53e527]{margin:0 auto}.name[data-v-9f53e527]{color:var(--vp-home-hero-name-color)}.clip[data-v-9f53e527]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-9f53e527],.text[data-v-9f53e527]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-9f53e527],.text[data-v-9f53e527]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-9f53e527],.VPHero.has-image .text[data-v-9f53e527]{margin:0}}.tagline[data-v-9f53e527]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-9f53e527]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-9f53e527]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-9f53e527]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-9f53e527]{margin:0}}.actions[data-v-9f53e527]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-9f53e527]{justify-content:center}@media (min-width: 640px){.actions[data-v-9f53e527]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-9f53e527]{justify-content:flex-start}}.action[data-v-9f53e527]{flex-shrink:0;padding:6px}.image[data-v-9f53e527]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-9f53e527]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-9f53e527]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-9f53e527]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-9f53e527]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-9f53e527]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-9f53e527]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-9f53e527]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-9f53e527]{width:320px;height:320px}}[data-v-9f53e527] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-9f53e527] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-9f53e527] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-de84e358]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-de84e358]:hover{border-color:var(--vp-c-brand);background-color:var(--vp-c-bg-soft-up)}.box[data-v-de84e358]{display:flex;flex-direction:column;padding:24px;height:100%}.VPFeature[data-v-de84e358] .VPImage{width:48px;height:48px;margin-bottom:20px}.icon[data-v-de84e358]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-bg-soft-down);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-de84e358]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-de84e358]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-de84e358]{padding-top:8px}.link-text-value[data-v-de84e358]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand)}.link-text-icon[data-v-de84e358]{display:inline-block;margin-left:6px;width:14px;height:14px;fill:currentColor}.VPFeatures[data-v-b8390164]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-b8390164]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-b8390164]{padding:0 64px}}.container[data-v-b8390164]{margin:0 auto;max-width:1152px}.items[data-v-b8390164]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-b8390164]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-b8390164],.item.grid-4[data-v-b8390164],.item.grid-6[data-v-b8390164]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-b8390164],.item.grid-4[data-v-b8390164]{width:50%}.item.grid-3[data-v-b8390164],.item.grid-6[data-v-b8390164]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-b8390164]{width:25%}}.VPHome[data-v-dfb75c6d]{padding-bottom:96px}.VPHome[data-v-dfb75c6d] .VPHomeSponsors{margin-top:112px;margin-bottom:-128px}@media (min-width: 768px){.VPHome[data-v-dfb75c6d]{padding-bottom:128px}}.VPDocAsideOutline[data-v-096ef0a5]{display:none}.VPDocAsideOutline.has-outline[data-v-096ef0a5]{display:block}.content[data-v-096ef0a5]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-096ef0a5]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:1px;height:18px;background-color:var(--vp-c-brand);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-096ef0a5]{letter-spacing:.4px;line-height:28px;font-size:13px;font-weight:600}.VPDocAside[data-v-a773ec5b]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-a773ec5b]{flex-grow:1}.VPDocAside[data-v-a773ec5b] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-a773ec5b] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-a773ec5b] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-a02285cd]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-a02285cd]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-0fee921e]{margin-top:64px}.edit-info[data-v-0fee921e]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-0fee921e]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-0fee921e]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand);transition:color .25s}.edit-link-button[data-v-0fee921e]:hover{color:var(--vp-c-brand-dark)}.edit-link-icon[data-v-0fee921e]{margin-right:8px;width:14px;height:14px;fill:currentColor}.prev-next[data-v-0fee921e]{border-top:1px solid var(--vp-c-divider);padding-top:24px}@media (min-width: 640px){.prev-next[data-v-0fee921e]{display:flex}}.pager.has-prev[data-v-0fee921e]{padding-top:8px}@media (min-width: 640px){.pager[data-v-0fee921e]{display:flex;flex-direction:column;flex-shrink:0;width:50%}.pager.has-prev[data-v-0fee921e]{padding-top:0;padding-left:16px}}.pager-link[data-v-0fee921e]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-0fee921e]:hover{border-color:var(--vp-c-brand)}.pager-link.next[data-v-0fee921e]{margin-left:auto;text-align:right}.desc[data-v-0fee921e]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-0fee921e]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand);transition:color .25s}.VPDocOutlineDropdown[data-v-115d6c42]{margin-bottom:42px}.VPDocOutlineDropdown button[data-v-115d6c42]{display:block;font-size:14px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;border:1px solid var(--vp-c-border);padding:4px 12px;border-radius:8px}.VPDocOutlineDropdown button[data-v-115d6c42]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPDocOutlineDropdown button.open[data-v-115d6c42]{color:var(--vp-c-text-1)}.icon[data-v-115d6c42]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}[data-v-115d6c42] .outline-link{font-size:13px}.open>.icon[data-v-115d6c42]{transform:rotate(90deg)}.items[data-v-115d6c42]{margin-top:10px;border-left:1px solid var(--vp-c-divider)}.VPDoc[data-v-cbd4323a]{padding:32px 24px 96px;width:100%}.VPDoc .VPDocOutlineDropdown[data-v-cbd4323a]{display:none}@media (min-width: 960px) and (max-width: 1280px){.VPDoc .VPDocOutlineDropdown[data-v-cbd4323a]{display:block}}@media (min-width: 768px){.VPDoc[data-v-cbd4323a]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-cbd4323a]{padding:32px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-cbd4323a]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-cbd4323a]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-cbd4323a]{display:flex;justify-content:center}.VPDoc .aside[data-v-cbd4323a]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-cbd4323a]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-cbd4323a]{max-width:1104px}}.container[data-v-cbd4323a]{margin:0 auto;width:100%}.aside[data-v-cbd4323a]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-cbd4323a]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-cbd4323a]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 32px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-cbd4323a]::-webkit-scrollbar{display:none}.aside-curtain[data-v-cbd4323a]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-cbd4323a]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 32px));padding-bottom:32px}.content[data-v-cbd4323a]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-cbd4323a]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-cbd4323a]{order:1;margin:0;min-width:640px}}.content-container[data-v-cbd4323a]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-cbd4323a]{max-width:688px}.NotFound[data-v-867fe174]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-867fe174]{padding:96px 32px 168px}}.code[data-v-867fe174]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-867fe174]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-867fe174]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-867fe174]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-867fe174]{padding-top:20px}.link[data-v-867fe174]{display:inline-block;border:1px solid var(--vp-c-brand);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand);transition:border-color .25s,color .25s}.link[data-v-867fe174]:hover{border-color:var(--vp-c-brand-dark);color:var(--vp-c-brand-dark)}.VPContent[data-v-c954fd0c]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-c954fd0c]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-c954fd0c]{margin:0}@media (min-width: 960px){.VPContent[data-v-c954fd0c]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-c954fd0c]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-c954fd0c]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-f3a6e121]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-f3a6e121]{display:none}@media (min-width: 768px){.VPFooter[data-v-f3a6e121]{padding:32px}}.container[data-v-f3a6e121]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-f3a6e121],.copyright[data-v-f3a6e121]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.message[data-v-f3a6e121]{order:2}.copyright[data-v-f3a6e121]{order:1}.Layout[data-v-1a0cf8a6]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-4c714ec0]{border-top:1px solid var(--vp-c-gutter);padding:88px 24px 96px;background-color:var(--vp-c-bg)}.container[data-v-4c714ec0]{margin:0 auto;max-width:1152px}.love[data-v-4c714ec0]{margin:0 auto;width:28px;height:28px;color:var(--vp-c-text-3)}.icon[data-v-4c714ec0]{width:28px;height:28px;fill:currentColor}.message[data-v-4c714ec0]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-4c714ec0]{padding-top:32px}.action[data-v-4c714ec0]{padding-top:40px;text-align:center}.VPTeamPage[data-v-35049cab]{padding-bottom:96px}@media (min-width: 768px){.VPTeamPage[data-v-35049cab]{padding-bottom:128px}}.VPTeamPageSection+.VPTeamPageSection[data-v-35049cab-s],.VPTeamMembers+.VPTeamPageSection[data-v-35049cab-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-35049cab-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-35049cab-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-35049cab-s],.VPTeamMembers+.VPTeamPageSection[data-v-35049cab-s]{margin-top:96px}}.VPTeamMembers[data-v-35049cab-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-35049cab-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-35049cab-s]{padding:0 64px}}.VPTeamPageTitle[data-v-c541cdfc]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-c541cdfc]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-c541cdfc]{padding:80px 64px 48px}}.title[data-v-c541cdfc]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-c541cdfc]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-c541cdfc]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-c541cdfc]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-f745734a]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-f745734a]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-f745734a]{padding:0 64px}}.title[data-v-f745734a]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-f745734a]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-f745734a]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-f745734a]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-f745734a]{padding-top:40px}.VPTeamMembersItem[data-v-d985852c]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-d985852c]{padding:32px}.VPTeamMembersItem.small .data[data-v-d985852c]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-d985852c]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-d985852c]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-d985852c]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-d985852c]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-d985852c]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-d985852c]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-d985852c]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-d985852c]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-d985852c]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-d985852c]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-d985852c]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-d985852c]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-d985852c]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-d985852c]{text-align:center}.avatar[data-v-d985852c]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-d985852c]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-d985852c]{margin:0;font-weight:600}.affiliation[data-v-d985852c]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-d985852c]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-d985852c]:hover{color:var(--vp-c-brand)}.desc[data-v-d985852c]{margin:0 auto}.desc[data-v-d985852c] a{font-weight:500;color:var(--vp-c-brand);text-decoration-style:dotted;transition:color .25s}.links[data-v-d985852c]{display:flex;justify-content:center;height:56px}.sp-link[data-v-d985852c]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-d985852c]:hover,.sp .sp-link.link[data-v-d985852c]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-d985852c]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPTeamMembers.small .container[data-v-0aa656ab]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-0aa656ab]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-0aa656ab]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-0aa656ab]{max-width:876px}.VPTeamMembers.medium .container[data-v-0aa656ab]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-0aa656ab]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-0aa656ab]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-0aa656ab]{max-width:760px}.container[data-v-0aa656ab]{display:grid;gap:24px;margin:0 auto;max-width:1152px}ul.table-of-contents{list-style-type:none;margin:1rem 0 0 .5rem;padding:0;line-height:1}ul.table-of-contents ul{margin-left:1rem}.table-of-contents li{text-indent:-5px}.table-of-contents li:before{content:"- ";text-indent:-5px} diff --git a/assets/utils_index.md.de0920c7.js b/assets/utils_index.md.de0920c7.js new file mode 100644 index 00000000..41885338 --- /dev/null +++ b/assets/utils_index.md.de0920c7.js @@ -0,0 +1,10 @@ +import{_ as e,o as n,c as l,z as s,a as t,t as o,O as p}from"./chunks/framework.2958c35d.js";const _=JSON.parse('{"title":"Utils","description":"","frontmatter":{"title":"Utils"},"headers":[],"relativePath":"utils/index.md","filePath":"utils/index.md"}'),r={name:"utils/index.md"},c={id:"frontmatter-title",tabindex:"-1"},i=s("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{ $frontmatter.title }}"'},"​",-1),D=p(`

JwtService

@see JwtService

Using jsonwebtoken

Example Extra Params Usage

typescript
import { JwtService } from '@jmondi/oauth2-server';
+
+export class MyCustomJwtService extends JwtService {
+  extraTokenFields({ user, client }: ExtraAccessTokenFieldArgs) {
+    return {
+      email: user?.email,
+      client_id: client.id,
+    }
+  }
+}

DateInterval

using ms

`,7);function y(a,F,C,A,d,h){return n(),l("div",null,[s("h1",c,[t(o(a.$frontmatter.title)+" ",1),i]),D])}const u=e(r,[["render",y]]);export{_ as __pageData,u as default}; diff --git a/assets/utils_index.md.de0920c7.lean.js b/assets/utils_index.md.de0920c7.lean.js new file mode 100644 index 00000000..65d2b35f --- /dev/null +++ b/assets/utils_index.md.de0920c7.lean.js @@ -0,0 +1 @@ +import{_ as e,o as n,c as l,z as s,a as t,t as o,O as p}from"./chunks/framework.2958c35d.js";const _=JSON.parse('{"title":"Utils","description":"","frontmatter":{"title":"Utils"},"headers":[],"relativePath":"utils/index.md","filePath":"utils/index.md"}'),r={name:"utils/index.md"},c={id:"frontmatter-title",tabindex:"-1"},i=s("a",{class:"header-anchor",href:"#frontmatter-title","aria-label":'Permalink to "{{ $frontmatter.title }}"'},"​",-1),D=p("",7);function y(a,F,C,A,d,h){return n(),l("div",null,[s("h1",c,[t(o(a.$frontmatter.title)+" ",1),i]),D])}const u=e(r,[["render",y]]);export{_ as __pageData,u as default}; diff --git a/configuration/index.html b/configuration/index.html new file mode 100644 index 00000000..1900edd7 --- /dev/null +++ b/configuration/index.html @@ -0,0 +1,36 @@ + + + + + + Configuration | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Configuration

INFO

The default configuration is great for most users. You might not need to tweak anything here.

The authorization server has a few optional settings with the following default values;

ts
type AuthorizationServerOptions = {
+  requiresPKCE: true;
+  requiresS256: false;
+  notBeforeLeeway: 0;
+  tokenCID: "id" | "name";
+}
OptionNumberDefaultDetails
requiresPKCEbooleantruePKCE is enabled by default and recommended for all users. To support a legacy client without PKCE, disable this option. [Learn more]
requiresS256booleantrueDisabled by default. If you want to require all clients to use S256, you can enable that here. [Learn more]
notBeforeLeewaynumber0Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a NumericDate value.
tokenCID"id" or "name""id"Sets the JWT accessToken.cid to either the client.id or client.name.

In 3.x the default is "id", in v2.x the default was "name". [Learn more]

To configure these options, pass the value in as the last argument:

typescript
const authorizationServer = new AuthorizationServer(
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  new JwtService("secret-key"),
+  {
+    requiresS256: true,
+  }
+);

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/entities/index.html b/entities/index.html new file mode 100644 index 00000000..8dd1b590 --- /dev/null +++ b/entities/index.html @@ -0,0 +1,54 @@ + + + + + + Entity Interfaces | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Entity Interfaces

Client Entity

This entity represents the client that wants to access the resource server. The client will retrieve an access token from our authorization server and use it to access the resource server.

  • URI must be an absolute URI
  • The endpoint may include application/x-www-form-urlencoded formatted query component which must be retained when adding additional query params
  • the endpoint URI must not include a fragment component
typescript
interface OAuthClient {
+  id: string;
+  name: string;
+  secret?: string;
+  redirectUris: string[];
+  allowedGrants: GrantIdentifier[];
+  scopes: OAuthScope[];
+}

Auth Code Entity

The auth code is used to retrieve an access token from the authorization server.

typescript
interface OAuthAuthCode {
+  code: string;
+  redirectUri?: string;
+  codeChallenge?: string;
+  codeChallengeMethod?: CodeChallengeMethod;
+  expiresAt: Date;
+  user?: OAuthUser;
+  client: OAuthClient;
+  scopes: OAuthScope[];
+}

TIP

ts
type CodeChallengeMethod = "S256" | "plain";

Token Entity

The access and refresh token that can be used to authenticate into the resource server. The originatingAuthCodeId will be present only for tokens originating from the authorization code grant; see the revokeDescendantsOf() method on the Token Repository for its significance.

typescript
interface OAuthToken {
+  accessToken: string;
+  accessTokenExpiresAt: Date;
+  refreshToken?: string | null;
+  refreshTokenExpiresAt?: Date | null;
+  client: OAuthClient;
+  user?: OAuthUser | null;
+  scopes: OAuthScope[];
+  originatingAuthCodeId?: string;
+}

User Entity

The resource owner

typescript
interface OAuthUser {
+  id: string;
+  [key: string]: any;
+}

Scope Entity

Scopes are a way to limit an app’s access to a user’s data.

https://www.oauth.com/oauth2-servers/scope/

typescript
interface OAuthScope {
+  name: string;
+  [key: string]: any;
+}

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/getting_started/index.html b/getting_started/index.html new file mode 100644 index 00000000..fd6794eb --- /dev/null +++ b/getting_started/index.html @@ -0,0 +1,94 @@ + + + + + + Getting Started | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Getting Started

Install

npm

bash
pnpm add @jmondi/oauth2-server
bash
npm install --save @jmondi/oauth2-server
bash
yarn add @jmondi/oauth2-server

The Authorization Server

The AuthorizationServer depends on the repositories. By default, no grants are enabled; each grant is opt-in and must be enabled when creating the AuthorizationServer.

You can enable any grant types you would like to support.

typescript
const authorizationServer = new AuthorizationServer(
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  "secret-key",
+  {} // optional configuration
+);
+authorizationServer.enableGrantType("client_credentials");
+authorizationServer.enableGrantType("refresh_token");
+authorizationServer.enableGrantType({
+  grant: "authorization_code",
+  userRepository, 
+  authorizationCodeRepository,
+});

See the configuration documentation for a full list of config options.

The Token Endpoint

The /token endpoint is a back channel endpoint that issues a usable access token.

typescript
app.post("/token", async (req: Express.Request, res: Express.Response) => {
+  try {
+    const oauthResponse = await authorizationServer.respondToAccessTokenRequest(req);
+    return handleExpressResponse(res, oauthResponse);
+  } catch (e) {
+    handleExpressError(e, res);
+    return;
+  }
+});

The Authorize Endpoint

The /authorize endpoint is a front channel endpoint that issues an authorization code. The authorization code can then be exchanged to the AuthorizationServer endpoint for a useable access token.

The endpoint should redirect the user to login, and then to accept the scopes requested by the application, and only when the user accepts, should it send the user back to the clients redirect uri.

typescript
import { requestFromExpress } from "@jmondi/oauth2-server/express";
+
+app.get("/authorize", async (req: Express.Request, res: Express.Response) => {
+  try {
+    // Validate the HTTP request and return an AuthorizationRequest.
+    const authRequest = await authorizationServer.validateAuthorizationRequest(request, requestFromExpress(req));
+
+    // You will probably redirect the user to a login endpoint. 
+    if (!req.user) {
+      req.redirect("/login")
+      return;
+    }
+    // After login, the user should be redirected back with user in the session.
+    // You will need to manage the authorization query on the round trip.
+    // The auth request object can be serialized and saved into a user's session.
+
+    // Once the user has logged in set the user on the AuthorizationRequest
+    authRequest.user = req.user;
+    
+    // Once the user has approved or denied the client update the status
+    // (true = approved, false = denied)
+    authRequest.isAuthorizationApproved = getIsAuthorizationApprovedFromSession();
+
+    // If the user has not approved the client's authorization request, 
+    // the user should be redirected to the approval screen.
+    if (!authRequest.isAuthorizationApproved) {
+      // This form will ask the user to approve the client and the scopes requested.
+      // "Do you authorize Jason to: read contacts? write contacts?"
+      req.redirect("/scopes")
+      return;
+    }
+
+    // At this point the user has approved the client for authorization.
+    // Any last authorization requests such as Two Factor Authentication (2FA) can happen here.
+
+
+    // Redirect back to redirect_uri with `code` and `state` as url query params.
+    const oauthResponse = await authorizationServer.completeAuthorizationRequest(authRequest);
+    return handleExpressResponse(res, oauthResponse);
+  } catch (e) {
+    handleExpressError(e, res);
+  }
+});

Revoke Token

Note

Implementing this endpoint is optional, but recommended. RFC7009 “OAuth 2.0 Token Revocation”

The /token/revoke endpoint is a back channel endpoint that revokes an existing token.

typescript
app.post("/token/revoke", async (req: Express.Request, res: Express.Response) => {
+  try {
+    const oauthResponse = await authorizationServer.revoke(req);
+    return handleExpressResponse(res, oauthResponse);
+  } catch (e) {
+    handleExpressError(e, res);
+    return;
+  }
+});

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/glossary/index.html b/glossary/index.html new file mode 100644 index 00000000..c50514e8 --- /dev/null +++ b/glossary/index.html @@ -0,0 +1,23 @@ + + + + + + Glossary | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Glossary

Resource Server

The resource server is the OAuth 2.0 term for your API server. The resource server handles authenticated requests after the client has obtained an access token.

Client

The application attempting to gain access to the resource server. The client must have an OAuthClient

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/grants/authorization_code.html b/grants/authorization_code.html new file mode 100644 index 00000000..5bfb5ffd --- /dev/null +++ b/grants/authorization_code.html @@ -0,0 +1,72 @@ + + + + + + Authorization Code Grant (w/ PKCE) | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Authorization Code Grant (w/ PKCE)

A temporary code that the client will exchange for an access token. The user authorizes the application, they are redirected back to the application with a temporary code in the URL. The application exchanges that code for the access token.

Flow

Part One

The client redirects the user to the /authorize with the following query parameters:

  • response_type must be set to code
  • client_id is the client identifier you received when you first created the application
  • redirect_uri indicates the URL to return the user to after authorization is complete, such as org.example.app://redirect
  • state is a random string generated by your application, which you’ll verify later
  • code_challenge must match the The code challenge as generated below,
  • code_challenge_method – Either plain or S256, depending on whether the challenge is the plain verifier string or the SHA256 hash of the string. If this parameter is omitted, the server will assume plain.

TIP

The client secret should never be used during the Part One of the authorization_code flow.

View sample authorization_code (part 1) request
http
GET /authorize HTTP/1.1
+Host: example.com
+
+response_type=code
+&client_id=xxxxxxx
+&redirect_uri=http://localhost
+&scope="contacts.read contacts.write"
+&state=abcdefghijklmnopqrstuvwxyz123456789
+&code_challenge=92d3b56942866d1edf02c33339b7c3dc37c6201282bb238cb47f0d3289f28a93f1bdd8af6ca9913aed0c4c
+&code_challenge_method=S256

The user will be asked to login to the authorization server and approve the client and requested scopes.

If the user approves the client, they will be redirected from the authorization server to the provided redirect_uri with the following fields in the query string:

  • code is the authorization code that will soon be exchanged for a token
  • state is the random string provided and should be compared against the initially provided state
View sample authorization_code (part 1) response
http
HTTP/1.1 302 Found
+Location: http://localhost&code=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRfaWQiOiJhdXRoY29kZWNsaWVudCIsInJlZGlyZWN0X3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3QiLCJhdXRoX2NvZGVfaWQiOiJteS1zdXBlci1zZWNyZXQtYXV0aC1jb2RlIiwic2NvcGVzIjpbXSwiZXhwaXJlX3RpbWUiOjE2MDE3NTM3MzMsImNvZGVfY2hhbGxlbmdlIjoiT0RRd1pHTTRZelpsTnpNeU1qUXlaREF4WWpFNU1XWmtZMlJrTmpKbU1UbGxNbUkwTnpJMFpEbGtNR0psWWpGbE1tTXhPV1kyWkRJMVpEZGpNak13WWciLCJjb2RlX2NoYWxsZW5nZV9tZXRob2QiOiJTMjU2In0.OIEtZN5BHNaB4Mz0plUpGAP93EHyoil2smJiG3S_2BM&state=abcdefghijklmnopqrstuvwxyz123456789

Part Two

The client sends a POST to the /token endpoint with the following body:

  • grant_type must be set to authorization_code
  • client_id is the client identifier you received when you first created the application
  • client_secret (optional) is the client secret and should only be provided if the client is confidential
  • redirect_uri
  • code_verifier
  • code is the authorization code from the query string

Private Key Leak Potential

Clients such as Browser Based Apps and Native Mobile Apps should NEVER have or use a client_secret. That means the client_secret should be omitted both when initially creating the OAuthClient entity, and when making requests.

View sample authorization_code (part 2) request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=authorization_code
+&client_id=xxxxxxxxxx
+&client_secret=xxxxxxxxxx
+&redirect_uri=http://localhost
+&code_verifier=OTJkM2I1Njk0Mjg2NmQxZWRmMDJjMzMzMzliN2MzZGMzN2M2MjAxMjgyYmIyMzhjYjQ3ZjBkMzI4OWYyOGE5M2YxYmRkOGFmNmNhOTkxM2FlZDBjNGM
+&code=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRfaWQiOiJhdXRoY29kZWNsaWVudCIsInJlZGlyZWN0X3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3QiLCJhdXRoX2NvZGVfaWQiOiJteS1zdXBlci1zZWNyZXQtYXV0aC1jb2RlIiwic2NvcGVzIjpbXSwiZXhwaXJlX3RpbWUiOjE2MDE3NTM3MzMsImNvZGVfY2hhbGxlbmdlIjoiT0RRd1pHTTRZelpsTnpNeU1qUXlaREF4WWpFNU1XWmtZMlJrTmpKbU1UbGxNbUkwTnpJMFpEbGtNR0psWWpGbE1tTXhPV1kyWkRJMVpEZGpNak13WWciLCJjb2RlX2NoYWxsZW5nZV9tZXRob2QiOiJTMjU2In0.OIEtZN5BHNaB4Mz0plUpGAP93EHyoil2smJiG3S_2BM

The authorization server will respond with the following response

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and is used to authenticate into the resource server
  • refresh_token is a JWT signed token and can be used in with the refresh grant
  • scope is a space delimited list of scopes the token has access to
View sample authorization_code (part 2) response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDE3NTUxMDQsIm5iZiI6MTYwMTc1MTUwNCwiaWF0IjoxNjAxNzUxNTA0LCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGF1dGggY29kZSBjbGllbnQiLCJzY29wZSI6IiJ9.-V9x03iz-3ISRMdj9m1-FCKjmtfjvv6wqnBj6VZdW28',
+  refresh_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiJhdXRoY29kZWNsaWVudCIsImFjY2Vzc190b2tlbl9pZCI6Im5ldyB0b2tlbiIsInJlZnJlc2hfdG9rZW5faWQiOiJ0aGlzLWlzLW15LXN1cGVyLXNlY3JldC1yZWZyZXNoLXRva2VuIiwic2NvcGUiOiIiLCJleHBpcmVfdGltZSI6MTYwMTc1NTEwNCwiaWF0IjoxNjAxNzUxNTAzfQ.J_RUFD5-158atTmI98R95vowZWi4mUEXYCO7iNwzpK4',
+  scope: 'contacts.read contacts.write'
+}

PKCE

PKCE (RFC 7636) is an extension to the Authorization Code flow to prevent several attacks and to be able to securely perform the OAuth exchange from public clients.

By default, PKCE is enabled and encouraged for all users. If you need to support a legacy client system without PKCE, you can disable PKCE with the authorization server using the requiresPKCE configuration option.

Code Verifier

The code_verifier is part of the extended “PKCE” and helps mitigate the threat of having authorization codes intercepted.

Before initializing Part One of the authorization code flow, the client first creats a code_verifier. This is a cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long.

We can do this in Node using the native crypto package and a base64urlencode function:

typescript
import crypto from "node:crypto";
+
+const code_verifier = crypto.randomBytes(43).toString("hex");

@see https://www.oauth.com/oauth2-servers/pkce/authorization-request/

Code Challenge

Now we need to create a code_challenge from our code_verifier.

For devices that can perform a SHA256 hash, the code challenge is a BASE64-URL-encoded string of the SHA256 hash of the code verifier.

typescript
const code_challenge = base64urlencode(
+  crypto.createHash("sha256")
+    .update(code_verifier)
+    .digest()
+);

Clients that do not have the ability to perform a SHA256 hash are permitted to use the plain code_verifier string as the code_challenge.

typescript
const code_challenge = code_verifier;
Need a base64urlencode function?
typescript
function base64urlencode(str: string) {
+  return Buffer.from(str)
+    .toString("base64")
+    .replace(/\+/g, "-")
+    .replace(/\//g, "_")
+    .replace(/=/g, "");
+}

Revocation

Authorization codes are only valid for a single use. In addition, they can be explicitly revoked on a server that supports RFC7009 “OAuth 2.0 Token Revocation”.

An authorization code revocation request will include the following parameters:

  • token is the authorization code previously issued to the client
  • token_type_hint (optional) should be set to authorization_code
View sample revoke authorization_code request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+token_type_hint=authorization_code
+&refresh_token=xxxxxxxxx

The authorization server will respond with the following response

View sample revoke authorization_code response
http
HTTP/1.1 200 OK
+Cache-Control: no-store
+Pragma: no-cache

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/grants/client_credentials.html b/grants/client_credentials.html new file mode 100644 index 00000000..c499f3e7 --- /dev/null +++ b/grants/client_credentials.html @@ -0,0 +1,45 @@ + + + + + + Client Credentials Grant | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Client Credentials Grant

When applications request an access token to access their own resources, not on behalf of a user.

TIP

The client_credentials grant should only be used by clients that can hold a secret. No Browser or Native Mobile Apps should be using this grant.

Flow

The client sends a POST to the /token endpoint with the following body:

  • grant_type must be set to client_credentials
  • client_id is the client identifier you received when you first created the application
  • client_secret is the client secret
  • scope is a string with a space delimited list of requested scopes. The requested scopes must be valid for the client.
View sample client_credentials request

Did you know? You can authenticate by passing the client_id and client_secret as a query string, or through basic auth.

http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=client_credentials
+&client_id=xxxxxxxxxx
+&client_secret=xxxxxxxxxx
+&scope="contacts.read contacts.write"
http
POST /token HTTP/1.1
+Host: example.com
+Authorization: Basic MTpzdXBlci1zZWNyZXQtc2VjcmV0
+
+grant_type=client_credentials
+&scope="contacts.read contacts.write"

The authorization server will respond with the following response.

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and can be used to authenticate into the resource server
  • scope is a space delimited list of scopes the token has access to
View sample client_credentials response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+ 
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDE3MDY0NjYsIm5iZiI6MTYwMTcwMjg2NiwiaWF0IjoxNjAxNzAyODY2LCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGNsaWVudCIsInNjb3BlIjoiIn0.KcXoCP6u9uhvtOoistLBskESA0tyT2I1SDe5Yn9iM4I',
+  scope: 'contacts.create contacts.read'
+}

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/grants/implicit.html b/grants/implicit.html new file mode 100644 index 00000000..ca552a57 --- /dev/null +++ b/grants/implicit.html @@ -0,0 +1,23 @@ + + + + + + Implicit Grant | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Implicit Grant

Not Recommended

Using the Implicit Grant is no longer best practice

This grant is supported, but not documented. Industry best practice recommends using the Authorization Code Grant without a client secret for native and browser-based apps.

Please look at these great resources:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/grants/index.html b/grants/index.html new file mode 100644 index 00000000..4e9a4b0e --- /dev/null +++ b/grants/index.html @@ -0,0 +1,61 @@ + + + + + + Which Grant? | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Which Grant?

Grants are different ways a client can obtain an access_token that will authorize it to use the resource server.

Deciding which grant to use depends on the type of client the end user will be using.

+-------+
+| Start |
++-------+
+    V
+    |
+    
+    |
++------------------------+              +-----------------------+
+| Have a refresh token?  |>----Yes----->|  Refresh Token Grant  |
++------------------------+              +-----------------------+
+    V
+    |
+    No
+    |
++---------------------+                
+|     Who is the      |                  +--------------------------+
+| Access token owner? |>---A Machine---->| Client Credentials Grant |
++---------------------+                  +--------------------------+
+    V
+    |
+    |
+   A User
+    |
+    |
++----------------------+                
+| What type of client? |   
++----------------------+     
+    |
+    |                                 +---------------------------+
+    |>-----------Server App---------->| Auth Code Grant with PKCE |
+    |                                 +---------------------------+
+    |
+    |                                 +---------------------------+
+    |>-------Browser Based App------->| Auth Code Grant with PKCE |
+    |                                 +---------------------------+
+    |
+    |                                 +---------------------------+
+    |>-------Native Mobile App------->| Auth Code Grant with PKCE |
+                                      +---------------------------+

Refresh Token Grant

If the client already has a refresh token, it can use the Refresh Token Grant to obtain a new access token without requiring the user's interaction. This grant is useful for long-lived sessions and background processes.

Client Credentials Grant

If the access token owner is a machine, such as a server or an application acting on its own behalf, rather than an individual user, the client can use the Client Credentials Grant. This grant is designed for scenarios where the client needs to access resources autonomously without the context of a specific user.

Auth Code Grant with PKCE

If the access token owner is a user, the recommended grant is the Authorization Code Grant with Proof Key for Code Exchange (PKCE). This grant involves a series of steps where the client redirects the user to the authorization server, the user grants access, and the server provides an authorization code that the client exchanges for an access token. PKCE adds an extra layer of security to protect against authorization code interception attacks.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/grants/password.html b/grants/password.html new file mode 100644 index 00000000..3187944e --- /dev/null +++ b/grants/password.html @@ -0,0 +1,50 @@ + + + + + + Password Grant | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Password Grant

The Password Grant is for first party clients that are able to hold secrets (ie not Browser or Native Mobile Apps)

TIP

The client_credentials grant should only be used by clients that can hold a secret

Flow

A complete refresh token request will include the following parameters:

  • grant_type must be set to password
  • client_id is the client identifier you received when you first created the application
  • client_secret if the client is confidential (has a secret), this must be provided
  • username
  • password
  • scope (optional)
View sample password grant request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=password
+&client_id=xxxxxxxxx
+&client_secret=xxxxxxxxx
+&username=xxxxxxxxx
+&password=xxxxxxxxx
+&scope="contacts.read contacts.write"
http
POST /token HTTP/1.1
+Host: example.com
+Authorization: Basic Y4NmE4MzFhZGFkNzU2YWRhN
+
+grant_type=password
+&username=xxxxxxxxx
+&password=xxxxxxxxx
+&scope="contacts.read contacts.write"

The authorization server will respond with the following response

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and is used to authenticate into the resource server
  • refresh_token is a JWT signed token and can be used in with the refresh grant
  • scope is a space delimited list of scopes the token has access to
View sample password grant response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1MTJhYjlhNC1jNzg2LTQ4YTYtOGFkNi05NGM1M2E4ZGM2NTEiLCJleHAiOjE2MDE3NjcyOTksIm5iZiI6MTYwMTc2MzY5OSwiaWF0IjoxNjAxNzYzNjk5LCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGNsaWVudCIsInNjb3BlIjoiIn0.sX6SWc2Af8jn-izFnrLgNIcNuZz_tRLl2p7M3CzQwKg',
+  refresh_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIzNTYxNWYyZi0xM2ZhLTQ3MzEtODNhMS05ZTM0NTU2YWIzOTAiLCJhY2Nlc3NfdG9rZW5faWQiOiJuZXcgdG9rZW4iLCJyZWZyZXNoX3Rva2VuX2lkIjoidGhpcy1pcy1teS1zdXBlci1zZWNyZXQtcmVmcmVzaC10b2tlbiIsInNjb3BlIjoiIiwidXNlcl9pZCI6IjUxMmFiOWE0LWM3ODYtNDhhNi04YWQ2LTk0YzUzYThkYzY1MSIsImV4cGlyZV90aW1lIjoxNjAxNzY3Mjk5LCJpYXQiOjE2MDE3NjM2OTh9.SSa7miIdk3bxyzg0f3M9jKBXWjPgD4QEw-AU3SYvBk0',
+  scope: 'contacts.read contacts.write'
+}

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/grants/refresh_token.html b/grants/refresh_token.html new file mode 100644 index 00000000..fad54e2c --- /dev/null +++ b/grants/refresh_token.html @@ -0,0 +1,56 @@ + + + + + + Refresh Token Grant | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Refresh Token Grant

Access tokens eventually expire. The refresh token grant enables the client to obtain a new access_token from an existing refresh_token.

Flow

A complete refresh token request will include the following parameters:

  • grant_type must be set to refresh_token
  • client_id is the client identifier you received when you first created the application
  • client_secret if the client is confidential (has a secret), this must be provided
  • refresh_token must be the signed token previously issued to the client
  • scope (optional) the requested scope must not include any additional scopes that were not previously issued to the original token
View sample refresh_token request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=refresh_token
+&refresh_token=xxxxxxxxx
+&client_id=xxxxxxxxx
+&client_secret=xxxxxxxxx
+&scope="contacts.read contacts.write"
http
POST /token HTTP/1.1
+Host: example.com
+Authorization: Basic Y4NmE4MzFhZGFkNzU2YWRhN
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=refresh_token
+&refresh_token=xxxxxxxxx
+&scope="contacts.read contacts.write"

The authorization server will respond with the following response

  • token_type will always be Bearer
  • expires_in is the time the token will live in seconds
  • access_token is a JWT signed token and is used to authenticate into the resource server
  • refresh_token is a JWT signed token and can be used in with the refresh grant
  • scope is a space delimited list of scopes the token has access to
View sample refresh_token response
http
HTTP/1.1 200 OK
+Content-Type: application/json; charset=UTF-8
+Cache-Control: no-store
+Pragma: no-cache
+
+{
+  token_type: 'Bearer',
+  expires_in: 3600,
+  access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1MTJhYjlhNC1jNzg2LTQ4YTYtOGFkNi05NGM1M2E4ZGM2NTEiLCJleHAiOjE2MDE3NjcyMTIsIm5iZiI6MTYwMTc2MzYxMiwiaWF0IjoxNjAxNzYzNjEyLCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGNsaWVudCIsInNjb3BlIjoiIn0.PO4eKSDVsFuKvebEXndWbZsprgzjkzEfHI7cl4N0YpM',
+  refresh_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIzNTYxNWYyZi0xM2ZhLTQ3MzEtODNhMS05ZTM0NTU2YWIzOTAiLCJhY2Nlc3NfdG9rZW5faWQiOiJuZXcgdG9rZW4iLCJyZWZyZXNoX3Rva2VuX2lkIjoidGhpcy1pcy1teS1zdXBlci1zZWNyZXQtcmVmcmVzaC10b2tlbiIsInNjb3BlIjoiIiwidXNlcl9pZCI6IjUxMmFiOWE0LWM3ODYtNDhhNi04YWQ2LTk0YzUzYThkYzY1MSIsImV4cGlyZV90aW1lIjoxNjAxNzY3MjEyLCJpYXQiOjE2MDE3NjM2MTF9.du4KfAzelSA8hzBaqGlrSvPtH-BxOcoUBXW4HS3pJkM',
+  scope: 'contacts.read contacts.write'
+}

Revocation

Refresh tokens are only valid for a single use. In addition, they can be explicitly revoked on a server that supports RFC7009 “OAuth 2.0 Token Revocation”.

A refresh token revocation request will include the following parameters:

  • token is the signed token previously issued to the client
  • token_type_hint (optional) should be set to refresh_token
View sample revoke refresh_token request
http
POST /token HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+
+token_type_hint=refresh_token
+&refresh_token=xxxxxxxxx

The authorization server will respond with the following response

View sample revoke refresh_token response
http
HTTP/1.1 200 OK
+Cache-Control: no-store
+Pragma: no-cache

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json new file mode 100644 index 00000000..37fb2907 --- /dev/null +++ b/hashmap.json @@ -0,0 +1 @@ +{"grants_client_credentials.md":"c56b9192","sources_index.md":"6a0f1688","grants_password.md":"94ac36b5","grants_implicit.md":"7f4193d4","grants_index.md":"0db0021a","getting_started_index.md":"f2de24b4","entities_index.md":"ba015854","grants_refresh_token.md":"cdff34f8","glossary_index.md":"52c4ef34","index.md":"3fa01efd","repositories_index.md":"21008022","migration_v2_to_v3.md":"a4bad7c8","adapters_index.md":"b69060b9","utils_index.md":"de0920c7","grants_authorization_code.md":"a6daa690","configuration_index.md":"81fa051a"} diff --git a/index.html b/index.html new file mode 100644 index 00000000..ea425626 --- /dev/null +++ b/index.html @@ -0,0 +1,23 @@ + + + + + + TypeScript OAuth2.0 Server | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

TypeScript OAuth2.0 Server

🇺🇦 Support Ukraine 🇺🇦

@jmondi/oauth2-server is a standards compliant implementation of an OAuth 2.0 authorization server for Node, written in TypeScript.

Requires node >= 16

Out of the box it supports the following grants:

The following RFCs are implemented:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/migration/v2_to_v3.html b/migration/v2_to_v3.html new file mode 100644 index 00000000..08f6bdfd --- /dev/null +++ b/migration/v2_to_v3.html @@ -0,0 +1,50 @@ + + + + + + Migrating from v2 to v3 | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Migrating from v2 to v3

Upgrade Time Estimate: ESM? 10 minutes; no-ESM? Varies

This package is now pure ESM

The package is now entirely ESM (ECMAScript Modules). More details about this change can be found in Sindre Sorhus's writeup.

AuthorizationServer Updates

In v2.x, AuthorizationServer constructor required all repositories. In v3.x, it has been simplified.

Before (v2.x):

typescript
const authorizationServer = new AuthorizationServer(
+  authCodeRepository,
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  userRepository,
+  jwtService,
+  {
+    requiresS256: false, 
+    tokenCID: "name",
+  }
+);

After (v3.x):

typescript
const authorizationServer = new AuthorizationServer(
+  clientRepository,
+  accessTokenRepository,
+  scopeRepository,
+  new JwtService("secret-key"),
+  {
+    requiresS256: true,  
+    tokenCID: "id",
+  }
+);

Enabling Grants

In v3, enableGrantType has been updated for the "authorization_code" and "password" grants.

Authorization Code Grant

AuthorizationCodeGrant now requires a AuthorizationCodeRepository and a UserRepository.

Before (v2.x):

typescript
authorizationServer.enableGrantType("authorization_code");

After (v3.x):

typescript
authorizationServer.enableGrantType({
+  grant: "authorization_code",
+  userRepository, 
+  authorizationCodeRepository,
+});

Password Grant

PasswordGrant now requires a UserRepository.

Before (v2.x):

typescript
authorizationServer.enableGrantType("password");

After (v3.x):

typescript
authorizationServer.enableGrantType({
+  grant: "password",
+  userRepository, 
+});

AuthorizationServerOptions Default Configuration Updates

The default options for AuthorizationServer have been modified to better align with the OAuth 2.0 specification:

Optionv2.x Valuev3.x Value
requiresS256falsetrue
tokenCID"name""id"

Removed setOptions Method

The undocumented, public method setOptions has been removed in v3. Options can be set during AuthorizationServer initialization.

generateRandomToken Function Fix

A bug in the generateRandomToken function has been fixed in v3.x.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/repositories/index.html b/repositories/index.html new file mode 100644 index 00000000..d6036394 --- /dev/null +++ b/repositories/index.html @@ -0,0 +1,116 @@ + + + + + + Repository Interfaces | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Repository Interfaces

Auth Code Repository

OAuthAuthCodeRepository interface is utilized for managing OAuth authorization codes. It contains methods for retrieving an authorization code entity by its identifier, issuing a new authorization code, persisting an authorization code in the storage, checking if an authorization code has been revoked, and revoking an authorization code.

typescript
interface OAuthAuthCodeRepository {
+
+  // Fetch auth code entity from storage by code
+  getByIdentifier(authCodeCode: string): Promise<OAuthAuthCode>;
+
+  // An async call that should return an OAuthAuthCode that has not been 
+  // persisted to storage yet.
+  issueAuthCode(
+    client: OAuthClient, 
+    user: OAuthUser | undefined, 
+    scopes: OAuthScope[]
+  ): OAuthAuthCode | Promise<OAuthAuthCode>;
+
+  // An async call that should persist an OAuthAuthCode into your storage.
+  persist(authCode: OAuthAuthCode): Promise<void>;
+
+  // This async method is called when an auth code is validated by the 
+  // authorization server. Return `true` if the auth code has been 
+  // manually revoked. If the code is still valid return `false`
+  isRevoked(authCodeCode: string): Promise<boolean>;
+
+  revoke(authCodeCode: string): Promise<void>;
+}

Client Repository

OAuthClientRepository interface is used for managing OAuth clients. It includes methods for fetching a client entity from storage by the client ID and for validating the client using the grant type and client secret.

typescript
interface OAuthClientRepository {
+  // Fetch client entity from storage by client_id
+  getByIdentifier(clientId: string): Promise<OAuthClient>;
+
+  // check the grant type and secret against the client
+  isClientValid(
+    grantType: GrantIdentifier, 
+    client: OAuthClient, 
+    clientSecret?: string
+  ): Promise<boolean>;
+}

Scope Repository

The OAuthScopeRepository interface handles scope management. It defines methods for finding all scopes by their names and for finalizing the scopes. In the finalization, additional scopes can be added or removed after they've been validated against the client scopes.

typescript
interface OAuthScopeRepository {
+  // Find all scopes by scope names
+  getAllByIdentifiers(scopeNames: string[]): Promise<OAuthScope[]>;
+
+  // Scopes have already been validated against the client, if you arent 
+  // doing anything fancy with scopes, you can just `return scopes`,
+  // Otherwise, now is your chance to add or remove any final scopes 
+  // after they have already been validated against the client scopes
+  finalize(
+    scopes: OAuthScope[],
+    identifier: GrantIdentifier,
+    client: OAuthClient,
+    user_id?: string,
+  ): Promise<OAuthScope[]>;
+}

Token Repository

OAuthTokenRepository interface manages OAuth tokens. It contains methods for issuing a new token, persisting a token in the storage, issuing a refresh token, revoking tokens, and fetching a refresh token entity by the refresh token.

typescript
interface OAuthTokenRepository {
+  // An async call that should return an OAuthToken that has not been 
+  // persisted to storage yet.
+  issueToken(
+    client: OAuthClient,
+    scopes: OAuthScope[],
+    user?: OAuthUser
+  ): Promise<OAuthToken>;
+
+  // An async call that should persist an OAuthToken into your storage.
+  persist(accessToken: OAuthToken): Promise<void>;
+
+  // An async call that enhances an already-persisted OAuthToken with
+  // refresh token fields.
+  issueRefreshToken(
+    accessToken: OAuthToken,
+    client: OAuthClient,
+  ): Promise<OAuthToken>
+
+  // This async method is called when a refresh token is used to reissue 
+  // an access token. The original access token is revoked, and a new
+  // access token is issued.
+  revoke(accessToken: OAuthToken): Promise<void>;
+
+  // This async method, if implemented, will be called by the authorization
+  // code grant if the original authorization code is reused.
+  // See https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2 for why.
+  revokeDescendantsOf?(authCodeId: string): Promise<void>;
+
+  // This async method is called when an access token is validated by the 
+  // authorization server. Return `true` if the access token has been 
+  // manually revoked. If the token is still valid return `false`
+  isRefreshTokenRevoked(refreshToken: OAuthToken): Promise<boolean>;
+
+  // Fetch refresh token entity from storage by refresh token
+  getByRefreshToken(refreshTokenToken: string): Promise<OAuthToken>;
+}

User Repository

The OAuthUserRepository interface handles user management. It defines methods for fetching a user entity from storage by their credentials and optional grant type and client. This may involve validating the user's credentials.

typescript
interface OAuthUserRepository {
+
+  // Fetch user entity from storage by identifier. A provided password may 
+  // be used to validate the users credentials. Grant type and client are provided
+  // for additional checks if desired
+  getUserByCredentials(
+    identifier: string,
+    password?: string,
+    grantType?: GrantIdentifier,
+    client?: OAuthClient,
+  ): Promise<OAuthUser | undefined>;
+}

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/sources/index.html b/sources/index.html new file mode 100644 index 00000000..ecd79975 --- /dev/null +++ b/sources/index.html @@ -0,0 +1,23 @@ + + + + + + Sources | @jmondi/oauth2-server + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/utils/index.html b/utils/index.html new file mode 100644 index 00000000..63605cf4 --- /dev/null +++ b/utils/index.html @@ -0,0 +1,32 @@ + + + + + + Utils | @jmondi/oauth2-server + + + + + + + + + + + +
Skip to content
On this page

Utils

JwtService

@see JwtService

Using jsonwebtoken

Example Extra Params Usage

typescript
import { JwtService } from '@jmondi/oauth2-server';
+
+export class MyCustomJwtService extends JwtService {
+  extraTokenFields({ user, client }: ExtraAccessTokenFieldArgs) {
+    return {
+      email: user?.email,
+      client_id: client.id,
+    }
+  }
+}

DateInterval

using ms

Released under the MIT License.

+ + + + \ No newline at end of file