=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each((function(){null!=this.parentNode&&this.parentNode.removeChild(this)}))},each:function(t){return a.every.call(this,(function(e,n){return!1!==t.call(e,n,e)})),this},filter:function(t){return P(t)?this.not(this.not(t)):i(c.call(this,(function(e){return O.matches(e,t)})))},add:function(t,e){return i(o(this.concat(i(t,e))))},is:function(t){return this.length>0&&O.matches(this[0],t)},not:function(t){var n=[];if(P(t)&&t.call!==e)this.each((function(e){t.call(this,e)||n.push(this)}));else{var s="string"==typeof t?this.filter(t):q(t)&&P(t.item)?l.call(t):i(t);this.forEach((function(t){s.indexOf(t)<0&&n.push(t)}))}return i(n)},has:function(t){return this.filter((function(){return F(t)?i.contains(this,t):i(this).find(t).size()}))},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!F(t)?t:i(t)},last:function(){var t=this[this.length-1];return t&&!F(t)?t:i(t)},find:function(t){var e=this;return t?"object"==typeof t?i(t).filter((function(){var t=this;return a.some.call(e,(function(e){return i.contains(e,t)}))})):1==this.length?i(O.qsa(this[0],t)):this.map((function(){return O.qsa(this,t)})):i()},closest:function(t,e){var n=[],s="object"==typeof t&&i(t);return this.each((function(i,r){for(;r&&!(s?s.indexOf(r)>=0:O.matches(r,t));)r=r!==e&&!M(r)&&r.parentNode;r&&n.indexOf(r)<0&&n.push(r)})),i(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=i.map(n,(function(t){if((t=t.parentNode)&&!M(t)&&e.indexOf(t)<0)return e.push(t),t}));return Z(e,t)},parent:function(t){return Z(o(this.pluck("parentNode")),t)},children:function(t){return Z(this.map((function(){return U(this)})),t)},contents:function(){return this.map((function(){return this.contentDocument||l.call(this.childNodes)}))},siblings:function(t){return Z(this.map((function(t,e){return c.call(U(e.parentNode),(function(t){return t!==e}))})),t)},empty:function(){return this.each((function(){this.innerHTML=""}))},pluck:function(t){return i.map(this,(function(e){return e[t]}))},show:function(){return this.each((function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=z(this.nodeName))}))},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=P(t);if(this[0]&&!e)var n=i(t).get(0),s=n.parentNode||this.length>1;return this.each((function(r){i(this).wrapAll(e?t.call(this,r):s?n.cloneNode(!0):n)}))},wrapAll:function(t){if(this[0]){var e;for(i(this[0]).before(t=i(t));(e=t.children()).length;)t=e.first();i(t).append(this)}return this},wrapInner:function(t){var e=P(t);return this.each((function(n){var s=i(this),r=s.contents(),o=e?t.call(this,n):t;r.length?r.wrapAll(o):s.append(o)}))},unwrap:function(){return this.parent().each((function(){i(this).replaceWith(i(this).children())})),this},clone:function(){return this.map((function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(t){return this.each((function(){var n=i(this);(t===e?"none"==n.css("display"):t)?n.show():n.hide()}))},prev:function(t){return i(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return i(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each((function(e){var n=this.innerHTML;i(this).empty().append(X(this,t,e,n))})):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each((function(e){var n=X(this,t,e,this.textContent);this.textContent=null==n?"":""+n})):0 in this?this.pluck("textContent").join(""):null},attr:function(t,i){var s;return"string"!=typeof t||1 in arguments?this.each((function(e){if(1===this.nodeType)if(F(t))for(n in t)G(this,n,t[n]);else G(this,t,X(this,i,e,this.getAttribute(t)))})):0 in this&&1==this[0].nodeType&&null!=(s=this[0].getAttribute(t))?s:e},removeAttr:function(t){return this.each((function(){1===this.nodeType&&t.split(" ").forEach((function(t){G(this,t)}),this)}))},prop:function(t,e){return t=N[t]||t,1 in arguments?this.each((function(n){this[t]=X(this,e,n,this[t])})):this[0]&&this[0][t]},removeProp:function(t){return t=N[t]||t,this.each((function(){delete this[t]}))},data:function(t,n){var i="data-"+t.replace(w,"-$1").toLowerCase(),s=1 in arguments?this.attr(i,n):this.attr(i);return null!==s?Y(s):e},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each((function(e){this.value=X(this,t,e,this.value)}))):this[0]&&(this[0].multiple?i(this[0]).find("option").filter((function(){return this.selected})).pluck("value"):this[0].value)},offset:function(e){if(e)return this.each((function(t){var n=i(this),s=X(this,e,t,n.offset()),r=n.offsetParent().offset(),o={top:s.top-r.top,left:s.left-r.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)}));if(!this.length)return null;if(h.documentElement!==this[0]&&!i.contains(h.documentElement,this[0]))return{top:0,left:0};var n=this[0].getBoundingClientRect();return{left:n.left+t.pageXOffset,top:n.top+t.pageYOffset,width:Math.round(n.width),height:Math.round(n.height)}},css:function(t,e){if(arguments.length<2){var s=this[0];if("string"==typeof t){if(!s)return;return s.style[r(t)]||getComputedStyle(s,"").getPropertyValue(t)}if(k(t)){if(!s)return;var o={},a=getComputedStyle(s,"");return i.each(t,(function(t,e){o[e]=s.style[r(e)]||a.getPropertyValue(e)})),o}}var u="";if("string"==I(t))e||0===e?u=B(t)+":"+j(t,e):this.each((function(){this.style.removeProperty(B(t))}));else for(n in t)t[n]||0===t[n]?u+=B(n)+":"+j(n,t[n])+";":this.each((function(){this.style.removeProperty(B(n))}));return this.each((function(){this.style.cssText+=";"+u}))},index:function(t){return t?this.indexOf(i(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&a.some.call(this,(function(t){return this.test(J(t))}),K(t))},addClass:function(t){return t?this.each((function(e){if("className"in this){s=[];var n=J(this);X(this,t,e,n).split(/\s+/g).forEach((function(t){i(this).hasClass(t)||s.push(t)}),this),s.length&&J(this,n+(n?" ":"")+s.join(" "))}})):this},removeClass:function(t){return this.each((function(n){if("className"in this){if(t===e)return J(this,"");s=J(this),X(this,t,n,s).split(/\s+/g).forEach((function(t){s=s.replace(K(t)," ")})),J(this,s.trim())}}))},toggleClass:function(t,n){return t?this.each((function(s){var r=i(this);X(this,t,s,J(this)).split(/\s+/g).forEach((function(t){(n===e?!r.hasClass(t):n)?r.addClass(t):r.removeClass(t)}))})):this},scrollTop:function(t){if(this.length){var n="scrollTop"in this[0];return t===e?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var n="scrollLeft"in this[0];return t===e?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),s=y.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(i(t).css("margin-top"))||0,n.left-=parseFloat(i(t).css("margin-left"))||0,s.top+=parseFloat(i(e[0]).css("border-top-width"))||0,s.left+=parseFloat(i(e[0]).css("border-left-width"))||0,{top:n.top-s.top,left:n.left-s.left}}},offsetParent:function(){return this.map((function(){for(var t=this.offsetParent||h.body;t&&!y.test(t.nodeName)&&"static"==i(t).css("position");)t=t.offsetParent;return t}))}},i.fn.detach=i.fn.remove,["width","height"].forEach((function(t){var n=t.replace(/./,(function(t){return t[0].toUpperCase()}));i.fn[t]=function(s){var r,o=this[0];return s===e?L(o)?o["inner"+n]:M(o)?o.documentElement["scroll"+n]:(r=this.offset())&&r[t]:this.each((function(e){(o=i(this)).css(t,X(this,s,e,o[t]()))}))}})),C.forEach((function(n,s){var r=s%2;i.fn[n]=function(){var n,o,a=i.map(arguments,(function(t){var s=[];return"array"==(n=I(t))?(t.forEach((function(t){return t.nodeType!==e?s.push(t):i.zepto.isZ(t)?s=s.concat(t.get()):void(s=s.concat(O.fragment(t)))})),s):"object"==n||null==t?t:O.fragment(t)})),u=this.length>1;return a.length<1?this:this.each((function(e,n){o=r?n:n.parentNode,n=0==s?n.nextSibling:1==s?n.firstChild:2==s?n:null;var c=i.contains(h.documentElement,o);a.forEach((function(e){if(u)e=e.cloneNode(!0);else if(!o)return i(e).remove();o.insertBefore(e,n),c&&tt(e,(function(e){if(!(null==e.nodeName||"SCRIPT"!==e.nodeName.toUpperCase()||e.type&&"text/javascript"!==e.type||e.src)){var n=e.ownerDocument?e.ownerDocument.defaultView:t;n.eval.call(n,e.innerHTML)}}))}))}))},i.fn[r?n+"To":"insert"+(s?"Before":"After")]=function(t){return i(t)[n](this),this}})),O.Z.prototype=Q.prototype=i.fn,O.uniq=o,O.deserializeValue=Y,i.zepto=O,i}();return function(e){var n,i=1,s=Array.prototype.slice,r=e.isFunction,o=function(t){return"string"==typeof t},a={},u={},c="onfocusin"in t,l={focus:"focusin",blur:"focusout"},h={mouseenter:"mouseover",mouseleave:"mouseout"};function p(t){return t._zid||(t._zid=i++)}function f(t,e,n,i){if((e=d(e)).ns)var s=g(e.ns);return(a[p(t)]||[]).filter((function(t){return t&&(!e.e||t.e==e.e)&&(!e.ns||s.test(t.ns))&&(!n||p(t.fn)===p(n))&&(!i||t.sel==i)}))}function d(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function g(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function m(t,e){return t.del&&!c&&t.e in l||!!e}function v(t){return h[t]||c&&l[t]||t}function y(t,i,s,r,o,u,c){var l=p(t),f=a[l]||(a[l]=[]);i.split(/\s/).forEach((function(i){if("ready"==i)return e(document).ready(s);var a=d(i);a.fn=s,a.sel=o,a.e in h&&(s=function(t){var n=t.relatedTarget;if(!n||n!==this&&!e.contains(this,n))return a.fn.apply(this,arguments)}),a.del=u;var l=u||s;a.proxy=function(e){if(!(e=S(e)).isImmediatePropagationStopped()){try{var i=Object.getOwnPropertyDescriptor(e,"data");i&&!i.writable||(e.data=r)}catch(e){}var s=l.apply(t,e._args==n?[e]:[e].concat(e._args));return!1===s&&(e.preventDefault(),e.stopPropagation()),s}},a.i=f.length,f.push(a),"addEventListener"in t&&t.addEventListener(v(a.e),a.proxy,m(a,c))}))}function w(t,e,n,i,s){var r=p(t);(e||"").split(/\s/).forEach((function(e){f(t,e,n,i).forEach((function(e){delete a[r][e.i],"removeEventListener"in t&&t.removeEventListener(v(e.e),e.proxy,m(e,s))}))}))}u.click=u.mousedown=u.mouseup=u.mousemove="MouseEvents",e.event={add:y,remove:w},e.proxy=function(t,n){var i=2 in arguments&&s.call(arguments,2);if(r(t)){var a=function(){return t.apply(n,i?i.concat(s.call(arguments)):arguments)};return a._zid=p(t),a}if(o(n))return i?(i.unshift(t[n],t),e.proxy.apply(null,i)):e.proxy(t[n],t);throw new TypeError("expected function")},e.fn.bind=function(t,e,n){return this.on(t,e,n)},e.fn.unbind=function(t,e){return this.off(t,e)},e.fn.one=function(t,e,n,i){return this.on(t,e,n,i,1)};var b=function(){return!0},C=function(){return!1},x=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,_={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};function S(t,i){if(i||!t.isDefaultPrevented){i||(i=t),e.each(_,(function(e,n){var s=i[e];t[e]=function(){return this[n]=b,s&&s.apply(i,arguments)},t[n]=C}));try{t.timeStamp||(t.timeStamp=Date.now())}catch(s){}(i.defaultPrevented!==n?i.defaultPrevented:"returnValue"in i?!1===i.returnValue:i.getPreventDefault&&i.getPreventDefault())&&(t.isDefaultPrevented=b)}return t}function E(t){var e,i={originalEvent:t};for(e in t)x.test(e)||t[e]===n||(i[e]=t[e]);return S(i,t)}e.fn.delegate=function(t,e,n){return this.on(e,t,n)},e.fn.undelegate=function(t,e,n){return this.off(e,t,n)},e.fn.live=function(t,n){return e(document.body).delegate(this.selector,t,n),this},e.fn.die=function(t,n){return e(document.body).undelegate(this.selector,t,n),this},e.fn.on=function(t,i,a,u,c){var l,h,p=this;return t&&!o(t)?(e.each(t,(function(t,e){p.on(t,i,a,e,c)})),p):(o(i)||r(u)||!1===u||(u=a,a=i,i=n),u!==n&&!1!==a||(u=a,a=n),!1===u&&(u=C),p.each((function(n,r){c&&(l=function(t){return w(r,t.type,u),u.apply(this,arguments)}),i&&(h=function(t){var n,o=e(t.target).closest(i,r).get(0);if(o&&o!==r)return n=e.extend(E(t),{currentTarget:o,liveFired:r}),(l||u).apply(o,[n].concat(s.call(arguments,1)))}),y(r,t,u,a,i,h||l)})))},e.fn.off=function(t,i,s){var a=this;return t&&!o(t)?(e.each(t,(function(t,e){a.off(t,i,e)})),a):(o(i)||r(s)||!1===s||(s=i,i=n),!1===s&&(s=C),a.each((function(){w(this,t,s,i)})))},e.fn.trigger=function(t,n){return(t=o(t)||e.isPlainObject(t)?e.Event(t):S(t))._args=n,this.each((function(){t.type in l&&"function"==typeof this[t.type]?this[t.type]():"dispatchEvent"in this?this.dispatchEvent(t):e(this).triggerHandler(t,n)}))},e.fn.triggerHandler=function(t,n){var i,s;return this.each((function(r,a){(i=E(o(t)?e.Event(t):t))._args=n,i.target=a,e.each(f(a,t.type||t),(function(t,e){if(s=e.proxy(i),i.isImmediatePropagationStopped())return!1}))})),s},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach((function(t){e.fn[t]=function(e){return 0 in arguments?this.bind(t,e):this.trigger(t)}})),e.Event=function(t,e){o(t)||(t=(e=t).type);var n=document.createEvent(u[t]||"Events"),i=!0;if(e)for(var s in e)"bubbles"==s?i=!!e[s]:n[s]=e[s];return n.initEvent(t,i,!0),S(n)}}(i),n=[],i.fn.remove=function(){return this.each((function(){this.parentNode&&("IMG"===this.tagName&&(n.push(this),this.src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=",e&&clearTimeout(e),e=setTimeout((function(){n=[]}),6e4)),this.parentNode.removeChild(this))}))},function(t){var e={},n=t.fn.data,i=t.camelCase,s=t.expando="Zepto"+ +new Date,r=[];function o(r,o){var u=r[s],c=u&&e[u];if(void 0===o)return c||a(r);if(c){if(o in c)return c[o];var l=i(o);if(l in c)return c[l]}return n.call(t(r),o)}function a(n,r,o){var a=n[s]||(n[s]=++t.uuid),c=e[a]||(e[a]=u(n));return void 0!==r&&(c[i(r)]=o),c}function u(e){var n={};return t.each(e.attributes||r,(function(e,s){0==s.name.indexOf("data-")&&(n[i(s.name.replace("data-",""))]=t.zepto.deserializeValue(s.value))})),n}t.fn.data=function(e,n){return void 0===n?t.isPlainObject(e)?this.each((function(n,i){t.each(e,(function(t,e){a(i,t,e)}))})):0 in this?o(this[0],e):void 0:this.each((function(){a(this,e,n)}))},t.data=function(e,n,i){return t(e).data(n,i)},t.hasData=function(n){var i=n[s],r=i&&e[i];return!!r&&!t.isEmptyObject(r)},t.fn.removeData=function(n){return"string"==typeof n&&(n=n.split(/\s+/)),this.each((function(){var r=this[s],o=r&&e[r];o&&t.each(n||o,(function(t){delete o[n?i(this):t]}))}))},["remove","empty"].forEach((function(e){var n=t.fn[e];t.fn[e]=function(){var t=this.find("*");return"remove"===e&&(t=t.add(this)),t.removeData(),n.call(this)}}))}(i),i}(e)},68937:t=>{"use strict";var e={}.hasOwnProperty,n=/[ -,\.\/:-@\[-\^`\{-~]/,i=/[ -,\.\/:-@\[\]\^`\{-~]/,s=/(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g,r=function t(r,o){"single"!=(o=function(t,n){if(!t)return n;var i={};for(var s in n)i[s]=e.call(t,s)?t[s]:n[s];return i}(o,t.options)).quotes&&"double"!=o.quotes&&(o.quotes="single");for(var a="double"==o.quotes?'"':"'",u=o.isIdentifier,c=r.charAt(0),l="",h=0,p=r.length;h126){if(d>=55296&&d<=56319&&h
{"use strict";var i,s,r,o=[n(45741),n(91856),n(41015),n(16486),n(45723),n(26345)],a=-1,u=[],c=!1;function l(){i&&s&&(i=!1,s.length?u=s.concat(u):a=-1,u.length&&h())}function h(){if(!i){c=!1,i=!0;for(var t=u.length,e=setTimeout(l);t;){for(s=u,u=[];s&&++a1)for(var n=1;n{"use strict";e.test=function(){return!n.g.setImmediate&&void 0!==n.g.MessageChannel},e.install=function(t){var e=new n.g.MessageChannel;return e.port1.onmessage=t,function(){e.port2.postMessage(0)}}},41015:(t,e,n)=>{"use strict";var i=n.g.MutationObserver||n.g.WebKitMutationObserver;e.test=function(){return i},e.install=function(t){var e=0,s=new i(t),r=n.g.document.createTextNode("");return s.observe(r,{characterData:!0}),function(){r.data=e=++e%2}}},91856:(t,e,n)=>{"use strict";e.test=function(){return"function"==typeof n.g.queueMicrotask},e.install=function(t){return function(){n.g.queueMicrotask(t)}}},45723:(t,e,n)=>{"use strict";e.test=function(){return"document"in n.g&&"onreadystatechange"in n.g.document.createElement("script")},e.install=function(t){return function(){var e=n.g.document.createElement("script");return e.onreadystatechange=function(){t(),e.onreadystatechange=null,e.parentNode.removeChild(e),e=null},n.g.document.documentElement.appendChild(e),t}}},26345:(t,e)=>{"use strict";e.test=function(){return!0},e.install=function(t){return function(){setTimeout(t,0)}}}}]);
\ No newline at end of file
diff --git a/pr-preview/pr-921/assets/js/489.3fe9939b.js.LICENSE.txt b/pr-preview/pr-921/assets/js/489.3fe9939b.js.LICENSE.txt
new file mode 100644
index 000000000..4f7ccd8a7
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/489.3fe9939b.js.LICENSE.txt
@@ -0,0 +1 @@
+/*! https://mths.be/cssesc v3.0.0 by @mathias */
diff --git a/pr-preview/pr-921/assets/js/4920f1c1.fe2056a7.js b/pr-preview/pr-921/assets/js/4920f1c1.fe2056a7.js
new file mode 100644
index 000000000..8a945592c
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/4920f1c1.fe2056a7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkopenfga_dev=self.webpackChunkopenfga_dev||[]).push([[6451],{18227:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>a,metadata:()=>n,toc:()=>d});const n=JSON.parse('{"id":"content/modeling/multiple-restrictions","title":"Multiple Restrictions","description":"Modeling system that requires multiple authorizations before allowing users to perform actions on particular objects","source":"@site/docs/content/modeling/multiple-restrictions.mdx","sourceDirName":"content/modeling","slug":"/modeling/multiple-restrictions","permalink":"/pr-preview/pr-921/docs/modeling/multiple-restrictions","draft":false,"unlisted":false,"editUrl":"https://github.com/openfga/openfga.dev/edit/main/docs/content/modeling/multiple-restrictions.mdx","tags":[],"version":"current","sidebarPosition":9,"frontMatter":{"sidebar_position":9,"slug":"/modeling/multiple-restrictions","description":"Modeling system that requires multiple authorizations before allowing users to perform actions on particular objects"},"sidebar":"docs","previous":{"title":"Public Access","permalink":"/pr-preview/pr-921/docs/modeling/public-access"},"next":{"title":"Custom Roles","permalink":"/pr-preview/pr-921/docs/modeling/custom-roles"}}');var o=i(74848),r=i(28453),s=i(89987);const a={sidebar_position:9,slug:"/modeling/multiple-restrictions",description:"Modeling system that requires multiple authorizations before allowing users to perform actions on particular objects"},l="Multiple Restrictions",c={},d=[{value:"Before You Start",id:"before-you-start",level:2},{value:"Modeling Parent-Child Objects",id:"modeling-parent-child-objects",level:3},{value:"Modeling Roles And Permissions",id:"modeling-roles-and-permissions",level:3},{value:" Concepts",id:"-concepts",level:3},{value:"Step By Step",id:"step-by-step",level:2},{value:"01. Add can_delete Relation To Only Allow Writers That Are Members Of The Ownership Organization",id:"01-add-can_delete-relation-to-only-allow-writers-that-are-members-of-the-ownership-organization",level:3},{value:"02. Verify That Our Solutions Work",id:"02-verify-that-our-solutions-work",level:3},{value:"Related Sections",id:"related-sections",level:2}];function h(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components},{Details:i}=t;return i||function(e,t){throw new Error("Expected "+(t?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.header,{children:(0,o.jsx)(t.h1,{id:"multiple-restrictions",children:"Multiple Restrictions"})}),"\n",(0,o.jsx)(s.ZE,{}),"\n",(0,o.jsxs)(t.p,{children:["In this guide we are going to model system that requires multiple authorizations before allowing users to perform actions on particular objects using ",(0,o.jsx)(s.bU,{format:s.Ed.ProductLink}),".\nFor example, ",(0,o.jsx)(t.em,{children:(0,o.jsx)(s.OK,{section:"what-is-a-user",linkName:"users"})})," are allowed to delete a ",(0,o.jsx)(t.code,{children:"document"})," if both of these conditions are met:"]}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"they are a member of the organization that owns the document"}),"\n",(0,o.jsx)(t.li,{children:"they have writer permissions on the document"}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"In this way, we prevent other users from deleting such document."}),"\n",(0,o.jsxs)(s.u6,{title:"When to use",appearance:"filled",children:[(0,o.jsx)(t.p,{children:"This is useful when:"}),(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Limiting certain actions (such as deleting or reading sensitive document) to privileged users."}),"\n",(0,o.jsx)(t.li,{children:"Adding restrictions and requiring multiple authorization paths before granting access."}),"\n"]})]}),"\n",(0,o.jsx)(t.h2,{id:"before-you-start",children:"Before You Start"}),"\n",(0,o.jsxs)(t.p,{children:["In order to understand this guide correctly you must be familiar with some ",(0,o.jsx)(s.OK,{})," and know how to develop the things that we will list below."]}),"\n",(0,o.jsxs)(i,{children:[(0,o.jsxs)("summary",{children:[(0,o.jsxs)(t.p,{children:["You will start with the ",(0,o.jsx)(t.em,{children:(0,o.jsx)(s.OK,{section:"what-is-an-authorization-model",linkName:"authorization model"})})," below,\nit represents a ",(0,o.jsx)(t.code,{children:"document"})," ",(0,o.jsx)(t.em,{children:(0,o.jsx)(s.OK,{section:"what-is-a-type",linkName:"type"})})," that can have users\n",(0,o.jsx)(t.strong,{children:(0,o.jsx)(s.OK,{section:"what-is-a-relation",linkName:"related"})})," as ",(0,o.jsx)(t.code,{children:"writer"})," and ",(0,o.jsx)(t.code,{children:"organizations"})," related as ",(0,o.jsx)(t.code,{children:"owner"}),".\nDocument's ",(0,o.jsx)(t.code,{children:"can_write"})," relation is based on whether user is a writer to the document. The ",(0,o.jsx)(t.code,{children:"organization"})," type can have users related as ",(0,o.jsx)(t.code,{children:"member"}),"."]}),(0,o.jsx)(t.p,{children:"Let us also assume that we have:"}),(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:["A ",(0,o.jsx)(t.code,{children:"document"}),' called "planning" owned by the ABC ',(0,o.jsx)(t.code,{children:"organization"}),"."]}),"\n",(0,o.jsxs)(t.li,{children:["Becky is a member of the ABC ",(0,o.jsx)(t.code,{children:"organization"}),"."]}),"\n",(0,o.jsxs)(t.li,{children:["Carl is a member of the XYZ ",(0,o.jsx)(t.code,{children:"organization"}),"."]}),"\n",(0,o.jsxs)(t.li,{children:["Becky and Carl both have ",(0,o.jsx)(t.code,{children:"writer"}),' access to the "planning" ',(0,o.jsx)(t.code,{children:"document"}),"."]}),"\n"]})]}),(0,o.jsx)(s.pB,{configuration:{schema_version:"1.1",type_definitions:[{type:"user"},{type:"document",relations:{owner:{this:{}},writer:{this:{}},can_write:{computedUserset:{object:"",relation:"writer"}}},metadata:{relations:{owner:{directly_related_user_types:[{type:"organization"}]},writer:{directly_related_user_types:[{type:"user"}]}}}},{type:"organization",relations:{member:{this:{}}},metadata:{relations:{member:{directly_related_user_types:[{type:"user"}]}}}}]}}),(0,o.jsx)(t.p,{children:"The current state of the system is represented by the following relationship tuples being in the system already:"}),(0,o.jsx)(s.AI,{relationshipTuples:[{_description:"organization ABC is the owner of planning document",user:"organization:ABC",relation:"owner",object:"document:planning"},{_description:"Becky is a writer to the planning document",user:"user:becky",relation:"writer",object:"document:planning"},{_description:"Carl is a writer to the planning document",user:"user:carl",relation:"writer",object:"document:planning"},{_description:"Becky is a member of the organization ABC",user:"user:becky",relation:"member",object:"organization:ABC"},{_description:"Carl is a member of the organization XYZ",user:"user:carl",relation:"member",object:"organization:XYZ"}]}),(0,o.jsx)(t.admonition,{type:"info",children:(0,o.jsx)(t.p,{children:"Note that we assign the organization, not the organization's members, as owner to the planning document."})}),(0,o.jsx)("hr",{}),(0,o.jsx)(t.p,{children:"In addition, you will need to know the following:"}),(0,o.jsx)(t.h3,{id:"modeling-parent-child-objects",children:"Modeling Parent-Child Objects"}),(0,o.jsxs)(t.p,{children:["You need to know how to model access based on parent-child relationships, e.g.: folders and documents. ",(0,o.jsx)(t.a,{href:"/pr-preview/pr-921/docs/modeling/parent-child",children:"Learn more \u2192"})]}),(0,o.jsx)(t.h3,{id:"modeling-roles-and-permissions",children:"Modeling Roles And Permissions"}),(0,o.jsxs)(t.p,{children:["You need to know how to model roles for users at the object level and model permissions for those roles. ",(0,o.jsx)(t.a,{href:"/pr-preview/pr-921/docs/modeling/roles-and-permissions",children:"Learn more \u2192"})]}),(0,o.jsxs)(t.h3,{id:"-concepts",children:[(0,o.jsx)(s.bU,{format:s.Ed.ShortForm})," Concepts"]}),(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:["A ",(0,o.jsx)(s.OK,{section:"what-is-a-type",linkName:"Type"}),": a class of objects that have similar characteristics"]}),"\n",(0,o.jsxs)(t.li,{children:["A ",(0,o.jsx)(s.OK,{section:"what-is-a-user",linkName:"User"}),": an entity in the system that can be related to an object"]}),"\n",(0,o.jsxs)(t.li,{children:["A ",(0,o.jsx)(s.OK,{section:"what-is-a-relation",linkName:"Relation"}),": is a string defined in the type definition of an authorization model that defines the possibility of a relationship between an object of the same type as the type definition and a user in the system"]}),"\n",(0,o.jsxs)(t.li,{children:["An ",(0,o.jsx)(s.OK,{section:"what-is-an-object",linkName:"Object"}),": represents an entity in the system. Users' relationships to it can be define through relationship tuples and the authorization model"]}),"\n",(0,o.jsxs)(t.li,{children:["A ",(0,o.jsx)(s.OK,{section:"what-is-a-relationship-tuple",linkName:"Relationship Tuple"}),": a grouping consisting of a user, a relation and an object stored in ",(0,o.jsx)(s.bU,{format:s.Ed.ShortForm})]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.a,{href:"/pr-preview/pr-921/docs/configuration-language#the-intersection-operator",children:"Intersection Operator"}),": the intersection operator can be used to indicate a relationship exists if the user is in all the sets of users"]}),"\n"]})]}),"\n",(0,o.jsx)(t.h2,{id:"step-by-step",children:"Step By Step"}),"\n",(0,o.jsxs)(t.p,{children:["With the above authorization model and relationship tuples, ",(0,o.jsx)(s.bU,{format:s.Ed.LongForm})," will correctly respond with ",(0,o.jsx)(t.code,{children:'{"allowed":true}'})," when *",(0,o.jsx)(s.OK,{section:"what-is-a-check-request",linkName:"check"}),"*is called to see if Carl and Becky can write this ",(0,o.jsx)(t.code,{children:"document"}),"."]}),"\n",(0,o.jsx)(t.p,{children:"We can verify that by issuing two check requests:"}),"\n",(0,o.jsx)(s.ou,{user:"user:becky",relation:"can_write",object:"document:planning",allowed:!0}),"\n",(0,o.jsx)(s.ou,{user:"user:carl",relation:"can_write",object:"document:planning",allowed:!0}),"\n",(0,o.jsx)(t.p,{children:"What we would like to do is offer a way so that a document can be written by Becky and Carl, but only writers who are also members of the organization that owns the document can remove it."}),"\n",(0,o.jsx)(t.p,{children:"To do this, we need to:"}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"#01-add-can_delete-relation-to-only-allow-writers-that-are-members-of-the-ownership-organization",children:"Add can_delete relation to only allow writers that are members of the ownership organization"})}),"\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"#02-verify-that-our-solutions-work",children:"Verify that our solutions work"})}),"\n"]}),"\n",(0,o.jsx)(t.h3,{id:"01-add-can_delete-relation-to-only-allow-writers-that-are-members-of-the-ownership-organization",children:"01. Add can_delete Relation To Only Allow Writers That Are Members Of The Ownership Organization"}),"\n",(0,o.jsxs)(t.p,{children:["The first step is to add the relation definition for ",(0,o.jsx)(t.code,{children:"can_delete"})," so that it requires users to be both ",(0,o.jsx)(t.code,{children:"writer"})," and ",(0,o.jsx)(t.code,{children:"member"})," of the owner. This is accomplished via the keyword ",(0,o.jsx)(t.a,{href:"/pr-preview/pr-921/docs/configuration-language#the-intersection-operator",children:(0,o.jsx)(t.code,{children:"and"})}),"."]}),"\n",(0,o.jsx)(s.pB,{configuration:{schema_version:"1.1",type_definitions:[{type:"user"},{type:"document",relations:{owner:{this:{}},writer:{this:{}},can_write:{computedUserset:{object:"",relation:"writer"}},can_delete:{intersection:{child:[{computedUserset:{object:"",relation:"writer"}},{tupleToUserset:{tupleset:{object:"",relation:"owner"},computedUserset:{object:"",relation:"member"}}}]}}},metadata:{relations:{owner:{directly_related_user_types:[{type:"organization"}]},writer:{directly_related_user_types:[{type:"user"}]}}}},{type:"organization",relations:{member:{this:{}}},metadata:{relations:{member:{directly_related_user_types:[{type:"user"}]}}}}]}}),"\n",(0,o.jsx)(t.h3,{id:"02-verify-that-our-solutions-work",children:"02. Verify That Our Solutions Work"}),"\n",(0,o.jsxs)(t.p,{children:["To verify that our solutions work, we need to check that Becky can delete the planning document because she is a writer AND she is a member of organization",":ABC"," that owns the planning document."]}),"\n",(0,o.jsx)(s.ou,{user:"user:becky",relation:"can_delete",object:"document:planning",allowed:!0}),"\n",(0,o.jsxs)(t.p,{children:["However, Carl cannot delete the planning document because although he is a writer, Carl is not a member of organization",":ABC"," that owns the planning document."]}),"\n",(0,o.jsx)(s.ou,{user:"user:carl",relation:"can_delete",object:"document:planning",allowed:!1}),"\n",(0,o.jsx)(t.h2,{id:"related-sections",children:"Related Sections"}),"\n",(0,o.jsx)(s.XQ,{description:"Check the following sections for more on how to model privileged access.",relatedLinks:[{title:"Modeling: User Groups",description:"Learn about how to add group members.",link:"./user-groups",id:"./user-groups"},{title:"Modeling: Blocklists",description:"Learn about how to set block lists.",link:"./blocklists",id:"./blocklists"},{title:"Modeling: Public Access",description:"Learn about model public access.",link:"./public-access",id:"./public-access"}]})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}}}]);
\ No newline at end of file
diff --git a/pr-preview/pr-921/assets/js/4a075682.db7af61f.js b/pr-preview/pr-921/assets/js/4a075682.db7af61f.js
new file mode 100644
index 000000000..596962c3a
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/4a075682.db7af61f.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkopenfga_dev=self.webpackChunkopenfga_dev||[]).push([[6898],{70719:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>d,default:()=>u,frontMatter:()=>a,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"content/modeling/overview","title":"Modeling Guides","description":"This section has guides, concepts and examples that help you define an authorization model.","source":"@site/docs/content/modeling/overview.mdx","sourceDirName":"content/modeling","slug":"/modeling","permalink":"/pr-preview/pr-921/docs/modeling","draft":false,"unlisted":false,"editUrl":"https://github.com/openfga/openfga.dev/edit/main/docs/content/modeling/overview.mdx","tags":[],"version":"current","sidebarPosition":0,"frontMatter":{"id":"overview","title":"Modeling Guides","slug":"/modeling","sidebar_position":0},"sidebar":"docs","previous":{"title":"Configure SDK Client Telemetry","permalink":"/pr-preview/pr-921/docs/getting-started/configure-telemetry"},"next":{"title":"Get Started with Modeling","permalink":"/pr-preview/pr-921/docs/modeling/getting-started"}}');var n=o(74848),s=o(28453),r=o(89987);const a={id:"overview",title:"Modeling Guides",slug:"/modeling",sidebar_position:0},d="Content",l={},c=[];function m(e){const t={h1:"h1",header:"header",p:"p",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.ZE,{}),"\n",(0,n.jsx)(t.p,{children:"This section has guides, concepts and examples that help you define an authorization model."}),"\n",(0,n.jsx)(r.rS,{title:"When to use",description:"The content in this section is useful:",listItems:["If you are starting with {ProductName} and want to learn how to represent your organization's/system's authorization needs.","If you are working on iterating on an authorization model you previously defined."]}),"\n",(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"content",children:"Content"})}),"\n",(0,n.jsx)(r.pV,{top:[{title:"Getting Started",description:"How to create an authorization model for your system starting from the requirements.",to:"modeling/getting-started"}],middle:[{title:"Direct Access",description:"Learn the basics of modeling authorization and granting access to users.",to:"modeling/direct-access"},{title:"User Groups",description:"Learn to model user group membership, and to grant access to all members of a group.",to:"modeling/user-groups"},{title:"Roles and Permissions",description:"Learn to model roles for users at the object level and model permissions for those roles.",to:"modeling/roles-and-permissions"},{title:"Parent-Child objects",description:"Learn to model access based on parent-child relationships, e.g.: folders and documents.",to:"modeling/parent-child"},{title:"Block Lists",description:"Learn to model denying access if users are part of list of blocked users.",to:"modeling/blocklists"},{title:"Public Access",description:"Learn to model giving everyone specific access to an object, e.g.: everyone can read.",to:"modeling/public-access"},{title:"Multiple Restrictions",description:"Learn to model requiring multiple privileges before granting access.",to:"modeling/multiple-restrictions"},{title:"Custom Roles",description:"Learn to model custom roles that are created by users.",to:"modeling/custom-roles"},{title:"Conditions",description:"Learn to model requiring dynamic attributes.",to:"modeling/conditions"},{title:"Contextual and Time-Based Authorization",description:"Learn to model and authorize when IP Address, time, and other dynamic and contextual restrictions are involved.",to:"modeling/contextual-time-based-authorization"},{title:"Authorization Through Organization Context",description:"Learn to model and authorize when a user belongs to multiple organizations.",to:"modeling/organization-context-authorization"}],bottom:[{title:"Building Blocks",description:"Learn the underlying concepts/building blocks that can be used to build any model.",to:"modeling/building-blocks"},{title:"Advanced Use-Cases",description:"Explore advanced use cases and patterns for authorization modeling with OpenFGA.",to:"modeling/advanced"},{title:"Migrating",description:"Learn to migrate relations and models in a production environment.",to:"modeling/migrating"}]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(m,{...e})}):m(e)}}}]);
\ No newline at end of file
diff --git a/pr-preview/pr-921/assets/js/4c2069ba.ce150ca4.js b/pr-preview/pr-921/assets/js/4c2069ba.ce150ca4.js
new file mode 100644
index 000000000..502baab93
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/4c2069ba.ce150ca4.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkopenfga_dev=self.webpackChunkopenfga_dev||[]).push([[4710],{36656:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>a,metadata:()=>t,toc:()=>d});const t=JSON.parse('{"id":"content/getting-started/production-best-practices","title":"Production Best Practices","description":"Best Practices of Running OpenFGA in a Production Environment","source":"@site/docs/content/getting-started/production-best-practices.mdx","sourceDirName":"content/getting-started","slug":"/getting-started/running-in-production","permalink":"/pr-preview/pr-921/docs/getting-started/running-in-production","draft":false,"unlisted":false,"editUrl":"https://github.com/openfga/openfga.dev/edit/main/docs/content/getting-started/production-best-practices.mdx","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"title":"Production Best Practices","description":"Best Practices of Running OpenFGA in a Production Environment","sidebar_position":8,"slug":"/getting-started/running-in-production"},"sidebar":"docs","previous":{"title":"Immutable Authorization Models","permalink":"/pr-preview/pr-921/docs/getting-started/immutable-models"},"next":{"title":"Implementation Best Practices","permalink":"/pr-preview/pr-921/docs/getting-started/tuples-api-best-practices"}}');var s=i(74848),r=i(28453),o=i(89987);const a={title:"Production Best Practices",description:"Best Practices of Running OpenFGA in a Production Environment",sidebar_position:8,slug:"/getting-started/running-in-production"},l="Running OpenFGA in Production",c={},d=[{value:"Cluster recommendations",id:"cluster-recommendations",level:2},{value:"Database recommendations",id:"database-recommendations",level:2},{value:"Concurrency limits",id:"concurrency-limits",level:2},{value:"Maximum results",id:"maximum-results",level:2},{value:"Related Sections",id:"related-sections",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"running-openfga-in-production",children:"Running OpenFGA in Production"})}),"\n",(0,s.jsx)(o.ZE,{}),"\n",(0,s.jsx)(n.p,{children:"The following list outlines best practices for running OpenFGA in a production environment:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/pr-preview/pr-921/docs/getting-started/setup-openfga/configure-openfga#configuring-authentication",children:"Configure Authentication"})}),"\n",(0,s.jsx)(n.li,{children:"Enable HTTP TLS or gRPC TLS or both"}),"\n",(0,s.jsx)(n.li,{children:'Set the log format to "json" and log level to "info"'}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/pr-preview/pr-921/docs/getting-started/setup-openfga/playground#disabling-the-playground",children:"Disable the Playground"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#cluster-recommendations",children:"Set Cluster"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#database-recommendations",children:"Set Database Options"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#maximum-results",children:"Set Maximum Results"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#concurrency-limits",children:"Set Concurrency Limits"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"cluster-recommendations",children:"Cluster recommendations"}),"\n",(0,s.jsx)(n.p,{children:"We recommend:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Turn on in-memory caching in Check API via flags. This will reduce latency of requests, but it will increase the staleness of OpenFGA's responses. Please see ",(0,s.jsx)(n.a,{href:"/pr-preview/pr-921/docs/interacting/consistency#cache-expiration",children:"Cache Expiration"})," for details on the flags."]}),"\n",(0,s.jsx)(n.li,{children:"Prefer having a small pool of servers with high capacity (memory and CPU cores) instead of a big pool of servers, to increase cache hit ratios and simplify pool management."}),"\n",(0,s.jsxs)(n.li,{children:["Turn on metrics collection via the flags ",(0,s.jsx)(n.code,{children:"--metrics-enabled"})," and ",(0,s.jsx)(n.code,{children:"--datastore-metrics-enabled"}),". This will allow you to debug issues."]}),"\n",(0,s.jsxs)(n.li,{children:["Turn on tracing via the flag ",(0,s.jsx)(n.code,{children:"--trace-enabled"}),", but set sampling ratio to a low value, for example ",(0,s.jsx)(n.code,{children:"--trace-sample-ratio=0.3"}),". This will allow you to debug issues without overwhelming the tracing server. However, keep in mind that enabling tracing comes with a slight performance cost."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"database-recommendations",children:"Database recommendations"}),"\n",(0,s.jsxs)(n.p,{children:["To ensure good performance for OpenFGA, it is recommended that the ",(0,s.jsx)(n.a,{href:"/pr-preview/pr-921/docs/getting-started/setup-openfga/configure-openfga#configuring-data-storage",children:"database"})," be:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Co-located in the same physical datacenter and network as your OpenFGA servers. This will minimize latency of database calls."}),"\n",(0,s.jsx)(n.li,{children:"Used exclusively for OpenFGA and not shared with other applications. This allows scaling the database independently and avoiding contention with your database."}),"\n",(0,s.jsxs)(n.li,{children:["Bootstrapped and managed with the ",(0,s.jsx)(n.code,{children:"openfga migrate"})," command. This will ensure the appropriate database indexes are created."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"It's strongly recommended to fine-tune your server database connection settings to avoid having to re-establish database connections frequently. Establishing database connections is slow and will negatively impact performance, and so here are some guidelines for managing database connection settings:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The server setting ",(0,s.jsx)(n.code,{children:"OPENFGA_DATASTORE_MAX_OPEN_CONNS"})," should be set to be equal to your database's max connections. For example, in Postgres, you can see this value via running the SQL query ",(0,s.jsx)(n.code,{children:"SHOW max_connections;"}),". If you are running multiple instances of the OpenFGA server, you should divide this setting equally among the instances. For example, if your database's ",(0,s.jsx)(n.code,{children:"max_connections"})," is 100, and you have 2 OpenFGA instances, ",(0,s.jsx)(n.code,{children:"OPENFGA_DATASTORE_MAX_OPEN_CONNS"})," should be set to 50 for each instance."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"OPENFGA_DATASTORE_MAX_IDLE_CONNS"})," should be set to a value no greater than the maximum open connections (see the bullet point above), but it should be set sufficiently high enough to avoid having to recreate connections on each request."]}),"\n",(0,s.jsx)(n.p,{children:"If, when monitoring your database stats, you see a lot of database connections being closed and subsequently reopened, then you should consider increasing the maximum number of idle connections."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If idle connections are getting reaped frequently, then consider increasing the ",(0,s.jsx)(n.code,{children:"OPENFGA_DATASTORE_CONN_MAX_IDLE_TIME"})," to a large value. When in doubt, prioritize keeping connections around for longer rather than shorter, because doing so will drastically improve performance."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"concurrency-limits",children:"Concurrency limits"}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["Before modifying concurrency limits please make sure you've followed the guidance for ",(0,s.jsx)(n.a,{href:"#database-recommendations",children:"Database Recommendations"})]})}),"\n",(0,s.jsx)(n.p,{children:"OpenFGA queries such as Check, ListObjects and ListUsers can be quite database and CPU intensive in some cases. If you notice that a single request is consuming a lot of CPU or creating a high degree of database contention, then you may consider setting some concurrency limits to protect other requests from being negatively impacted by overly aggressive queries."}),"\n",(0,s.jsx)(n.p,{children:"The following table enumerates the server's concurrency specific settings:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"flag"}),(0,s.jsx)(n.th,{children:"env"}),(0,s.jsx)(n.th,{children:"config"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"--max-concurrent-reads-for-list-objects"}),(0,s.jsx)(n.td,{children:"OPENFGA_MAX_CONCURRENT_READS_FOR_LIST_OBJECTS"}),(0,s.jsx)(n.td,{children:"maxConcurrentReadsForListObjects"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"--max-concurrent-reads-for-list-users"}),(0,s.jsx)(n.td,{children:"OPENFGA_MAX_CONCURRENT_READS_FOR_LIST_USERS"}),(0,s.jsx)(n.td,{children:"maxConcurrentReadsForListUsers"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"--max-concurrent-reads-for-check"}),(0,s.jsx)(n.td,{children:"OPENFGA_MAX_CONCURRENT_READS_FOR_CHECK"}),(0,s.jsx)(n.td,{children:"maxConcurrentReadsForCheck"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"--resolve-node-limit"}),(0,s.jsx)(n.td,{children:"OPENFGA_RESOLVE_NODE_LIMIT"}),(0,s.jsx)(n.td,{children:"resolveNodeLimit"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"--resolve-node-breadth-limit"}),(0,s.jsx)(n.td,{children:"OPENFGA_RESOLVE_NODE_BREADTH_LIMIT"}),(0,s.jsx)(n.td,{children:"resolveNodeBreadthLimit"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"--max-concurrent-checks-per-batch-check"}),(0,s.jsx)(n.td,{children:"OPENFGA_MAX_CONCURRENT_CHECKS_PER_BATCH_CHECK"}),(0,s.jsx)(n.td,{children:"maxConcurrentChecksPerBatchCheck"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"Determining the right values for these settings will be based on a variety of factors including, but not limited to, the database specific deployment topology, the FGA model(s) involved, and the relationship tuples in the system. However, here are some high-level guidelines:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If a single ListObjects or ListUsers query is negatively impacting other query endpoints by increasing their latency or their error rate, then consider setting a lower value for ",(0,s.jsx)(n.code,{children:"OPENFGA_MAX_CONCURRENT_READS_FOR_LIST_OBJECTS"})," or ",(0,s.jsx)(n.code,{children:"OPENFGA_MAX_CONCURRENT_READS_FOR_LIST_USERS"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If a single Check query is negatively impacting other query endpoints by increasing their latency or their error rate, then consider setting a lower value for ",(0,s.jsx)(n.code,{children:"OPENFGA_MAX_CONCURRENT_READS_FOR_CHECK"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["If you still see high request latencies despite the guidance above, then you may additionally consider setting stricter limits on the query resolution behavior by limiting the resolution depth and resolution breadth. These can be controlled with the ",(0,s.jsx)(n.code,{children:"OPENFGA_RESOLVE_NODE_LIMIT"})," and ",(0,s.jsx)(n.code,{children:"OPENFGA_RESOLVE_NODE_BREADTH_LIMIT"})," settings, respectively. Consider these guidelines:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"OPENFGA_RESOLVE_NODE_LIMIT"})," limits the resolution depth of a single query, and thus it sets an upper bound on how deep a relationship hierarchy may be. A high value will allow a single query to involve more hierarchical resolution and therefore more database queries, while a low value will reduce the number of hierarchical resolutions that will be allowed and thus reduce the number of database queries."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"OPENFGA_RESOLVE_NODE_BREADTH_LIMIT"})," limits the resolution breadth. It sets an upper bound on the number of in-flight resolutions that can be taking place on one or more ",(0,s.jsx)(n.a,{href:"/pr-preview/pr-921/docs/concepts#what-is-a-user",children:"usersets"}),". A high value will allow a single query to involve more concurrent evaluations to take place and therefore more database queries and server processes, while a low value will reduce the overall number of concurrent resolutions that will be allowed and thus reduce the number of database queries and server processes."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"maximum-results",children:"Maximum results"}),"\n",(0,s.jsx)(n.p,{children:"Both the ListObjects and ListUsers endpoints will continue retrieving results until one of the following conditions is met:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"The maximum number of results is found"}),"\n",(0,s.jsx)(n.li,{children:"The entire pool of possible results has been searched"}),"\n",(0,s.jsx)(n.li,{children:"The API times out"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["By default, both ListObjects and ListUsers have a maximum results limit of 1,000. The higher the quantity of potential results in the system, the more time and resource-intensive it becomes to search for a large number of maximum results. This increased load can impact performance, potentially leading to time-outs in some cases. If your use case allows, consider setting a lower max results value via the ",(0,s.jsx)(n.code,{children:"OPENFGA_LIST_OBJECTS_MAX_RESULTS"})," or ",(0,s.jsx)(n.code,{children:"OPENFGA_LIST_USERS_MAX_RESULTS"})," configuration properties. This adjustment can lead to immediate improvements in time and resource efficiency."]}),"\n",(0,s.jsx)(n.h2,{id:"related-sections",children:"Related Sections"}),"\n",(0,s.jsx)(o.XQ,{description:"Check the following sections for more on how to run OpenFGA in production environment.",relatedLinks:[{title:"Data and API Best Practices",description:"Learn the best practices for managing data and invoking APIs in production environment",link:"./tuples-api-best-practices",id:"./tuples-api-best-practices"},{title:"Migrating Relations",description:"Learn how to migrate relations in a production environment",link:"../modeling/migrating/migrating-relations",id:"../modeling/migrating/migrating-relations"}]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}}}]);
\ No newline at end of file
diff --git a/pr-preview/pr-921/assets/js/4d7851de.3c3ecab6.js b/pr-preview/pr-921/assets/js/4d7851de.3c3ecab6.js
new file mode 100644
index 000000000..8106ad25c
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/4d7851de.3c3ecab6.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkopenfga_dev=self.webpackChunkopenfga_dev||[]).push([[6509],{12755:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>c,frontMatter:()=>r,metadata:()=>a,toc:()=>h});var a=s(87636),n=s(74848),i=s(28453);const r={title:"List Users API",description:"List Users API",slug:"list-users-announcement",date:new Date("2024-05-30T00:00:00.000Z"),authors:"miparnisari",tags:["openfga","features"],image:"https://openfga.dev/img/og-rich-embed.png",hide_table_of_contents:!1},o="New ListUsers API on OpenFGA",l={authorsImageUrls:[void 0]},h=[{value:"How to use it?",id:"how-to-use-it",level:2},{value:"We want your feedback!",id:"we-want-your-feedback",level:2}];function p(e){const t={a:"a",code:"code",h2:"h2",p:"p",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"Today we are launching a new API for OpenFGA: ListUsers."}),"\n",(0,n.jsx)(t.p,{children:'This API will answer the question "what users have relation X with object Y?". This will be useful, for example, in UIs that want to display the list of users that a resource has been shared with, e.g. the "share" dialog in Google Docs.'}),"\n",(0,n.jsxs)(t.p,{children:["You can read more about it in the ",(0,n.jsx)(t.a,{href:"https://openfga.dev/api/service#/Relationship%20Queries/ListUsers",children:"API docs"})," and the ",(0,n.jsx)(t.a,{href:"https://openfga.dev/docs/getting-started/perform-list-users",children:"product documentation"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"how-to-use-it",children:"How to use it?"}),"\n",(0,n.jsxs)(t.p,{children:["ListUsers is available in OpenFGA starting with ",(0,n.jsx)(t.a,{href:"https://github.com/openfga/openfga/releases/tag/v1.5.4",children:"v1.5.4"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["To be able to call this API, you must turn on this flag on the server: ",(0,n.jsx)(t.code,{children:"--experimentals enable-list-users"}),". Be sure to also check out the various configuration flags that were added to control its behavior."]}),"\n",(0,n.jsxs)(t.p,{children:["The new functionality is available on the latest versions of the ",(0,n.jsx)(t.a,{href:"https://github.com/openfga/java-sdk/",children:"Java"}),", ",(0,n.jsx)(t.a,{href:"https://github.com/openfga/dotnet-sdk/",children:".NET"}),", ",(0,n.jsx)(t.a,{href:"https://github.com/openfga/go-sdk/",children:"Go"})," and ",(0,n.jsx)(t.a,{href:"https://github.com/openfga/js-sdk/",children:"Javascript SDK"}),", ",(0,n.jsx)(t.a,{href:"https://github.com/openfga/cli?tab=readme-ov-file#list-users",children:"CLI"})," and ",(0,n.jsx)(t.a,{href:"https://marketplace.visualstudio.com/items?itemName=openfga.openfga-vscode",children:"VS Code integration"}),"."]}),"\n",(0,n.jsx)(t.p,{children:"We'll be releasing support for the Python SDK soon."}),"\n",(0,n.jsx)(t.h2,{id:"we-want-your-feedback",children:"We want your feedback!"}),"\n",(0,n.jsx)(t.p,{children:"We want to learn how you use this API and how we can improve it!"}),"\n",(0,n.jsxs)(t.p,{children:["Please reach out through our ",(0,n.jsx)(t.a,{href:"https://openfga.dev/community",children:"community channels"})," with any questions or feedback."]})]})}function c(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},87636:e=>{e.exports=JSON.parse('{"permalink":"/pr-preview/pr-921/blog/list-users-announcement","source":"@site/blog/list-users-announcement.md","title":"List Users API","description":"List Users API","date":"2024-05-30T00:00:00.000Z","tags":[{"inline":true,"label":"openfga","permalink":"/pr-preview/pr-921/blog/tags/openfga"},{"inline":true,"label":"features","permalink":"/pr-preview/pr-921/blog/tags/features"}],"readingTime":0.895,"hasTruncateMarker":false,"authors":[{"name":"Maria Ines Parnisari","url":"https://github.com/miparnisari","imageURL":"/pr-preview/pr-921/img/blog/authors/miparnisari.jpg","key":"miparnisari","page":null}],"frontMatter":{"title":"List Users API","description":"List Users API","slug":"list-users-announcement","date":"2024-05-30T00:00:00.000Z","authors":"miparnisari","tags":["openfga","features"],"image":"https://openfga.dev/img/og-rich-embed.png","hide_table_of_contents":false},"unlisted":false,"prevItem":{"title":"Fine Grained News - May 2024","permalink":"/pr-preview/pr-921/blog/fine-grained-news-2024-05"},"nextItem":{"title":"Fine Grained News - April 2024","permalink":"/pr-preview/pr-921/blog/fine-grained-news-2024-04"}}')}}]);
\ No newline at end of file
diff --git a/pr-preview/pr-921/assets/js/5352c875.b4b123d7.js b/pr-preview/pr-921/assets/js/5352c875.b4b123d7.js
new file mode 100644
index 000000000..2f9b11c13
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/5352c875.b4b123d7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkopenfga_dev=self.webpackChunkopenfga_dev||[]).push([[2271],{41358:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>h,contentTitle:()=>o,default:()=>c,frontMatter:()=>r,metadata:()=>t,toc:()=>l});var t=i(34047),s=i(74848),a=i(28453);const r={title:"Fine Grained News - January 2024",description:"Fine Grained News",slug:"fine-grained-news-2024-01",date:new Date("2024-01-29T00:00:00.000Z"),authors:"aaguiar",tags:["newsletter"],image:"https://openfga.dev/img/og-rich-embed.png",hide_table_of_contents:!1},o="Fine Grained News",h={authorsImageUrls:[void 0]},l=[{value:"Team News",id:"team-news",level:2},{value:"KubeCon Europe 2024!",id:"kubecon-europe-2024",level:2},{value:"OpenFGA \u26a1\ufe0fEnlightning Session!",id:"openfga-\ufe0fenlightning-session",level:2},{value:"Visual Studio Code Integration Enhancements",id:"visual-studio-code-integration-enhancements",level:2},{value:"CLI improvements",id:"cli-improvements",level:2},{value:"OpenFGA v1.4.3",id:"openfga-v143",level:2},{value:"SDK Improvements",id:"sdk-improvements",level:2},{value:"Language Improvements",id:"language-improvements",level:2},{value:"Github Actions",id:"github-actions",level:2},{value:"What's Next? Check our RFCs!",id:"whats-next-check-our-rfcs",level:2},{value:"OpenFGA Community",id:"openfga-community",level:2},{value:"See you next month!",id:"see-you-next-month",level:2}];function d(e){const n={a:"a",h2:"h2",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"Welcome to the 2nd edition of Fine Grained News!"}),"\n",(0,s.jsx)(n.h2,{id:"team-news",children:"Team News"}),"\n",(0,s.jsx)(n.p,{children:"The OpenFGA team got bigger, and we met in person in Toronto for the first time! We got to know each other better, helped new team members to get familiar with the project, hacked some code, had some fun with ax throwing, and loved Toronto's weather!"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"OpenFGA Team",src:i(67618).A+"",width:"800",height:"502"})}),"\n",(0,s.jsx)(n.h2,{id:"kubecon-europe-2024",children:"KubeCon Europe 2024!"}),"\n",(0,s.jsx)(n.p,{children:"We got two presentations accepted in KubeCon Europe!"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://www.linkedin.com/in/jonathan-whitaker-5a8b2484/",children:"Jonathan Whitaker"})," from Okta will talk about ",(0,s.jsx)(n.a,{href:"https://kccnceu2024.sched.com/event/1YeQD",children:"Federated IAM for Kubernetes with OpenFGA"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://www.linkedin.com/in/paulinejamin/",children:"Pauline Jamin"})," from Agicap and ",(0,s.jsx)(n.a,{href:"https://www.linkedin.com/in/aaguiar/",children:"Andres Aguiar"})," from Okta will present on ",(0,s.jsx)(n.a,{href:"https://colocatedeventseu2024.sched.com/event/1YFhM/implementing-modern-cloud-native-authorization-using-openfga-andres-aguiar-okta-pauline-jamin-agicap",children:"Implementing Modern Cloud Native Authorization Using OpenFGA"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"We'll also have a Project Kiosk, so if you plan to attend let us know and we can schedule some time together!"}),"\n",(0,s.jsx)(n.h2,{id:"openfga-\ufe0fenlightning-session",children:"OpenFGA \u26a1\ufe0fEnlightning Session!"}),"\n",(0,s.jsxs)(n.p,{children:["Our own ",(0,s.jsx)(n.a,{href:"https://www.linkedin.com/in/raghdhamzeh/",children:"Raghd Hamzeh"})," will join ",(0,s.jsx)(n.a,{href:"https://twitter.com/wiggitywhitney",children:"Whitney Lee"})," in a Tanzu \u26a1\ufe0fEnlightning session on ",(0,s.jsx)(n.strong,{children:"February 8th at 9am PT"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Join their Youtube stream ",(0,s.jsx)(n.a,{href:"https://www.youtube.com/watch?v=yTgtAzhvC28",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"visual-studio-code-integration-enhancements",children:"Visual Studio Code Integration Enhancements"}),"\n",(0,s.jsx)(n.p,{children:"We keep investing in improving our VS Code experience. The video below shows how, in addition to validating the model, we can validate the tuple content and the tests."}),"\n",(0,s.jsx)(n.p,{children:"We are identifying:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Invalid object types, user types, and relations when defining tuples."}),"\n",(0,s.jsx)(n.li,{children:"Invalid object types, user types, and relations when defining tests."}),"\n",(0,s.jsx)(n.li,{children:"User id or object id that was not included in any tuple in check tests."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"This helps authoring/testing models, making the whole process less error prone and more fun!"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"VS Code",src:i(24044).A+"",width:"794",height:"599"})}),"\n",(0,s.jsx)(n.h2,{id:"cli-improvements",children:"CLI improvements"}),"\n",(0,s.jsx)(n.p,{children:"We love the FGA CLI and we keep making it even better."}),"\n",(0,s.jsx)(n.p,{children:"We had a few of contributions from new team members and the community :)."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"You can now import tuples from a CSV file. We supported JSON/YAML, but if you are exporting data from a database, producing to CSV is way simpler."}),"\n",(0,s.jsx)(n.li,{children:"You can take a .fga.yaml file with a model and tuples, and get it imported in OpenFGA."}),"\n",(0,s.jsx)(n.li,{children:"Added support for specifying an external tuple_file in .fga.yaml files."}),"\n",(0,s.jsx)(n.li,{children:"Added support for specifying a continuation_token when calling fga tuple changes."}),"\n",(0,s.jsx)(n.li,{children:"Support for configuring OAuth scopes to authenticate to OIDC servers."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Check the updated documentation in our ",(0,s.jsx)(n.a,{href:"https://github.com/openfga/cli",children:"CLI repository"})]}),"\n",(0,s.jsxs)(n.p,{children:["Thanks to ",(0,s.jsx)(n.a,{href:"https://github.com/le-yams",children:"Yann D'Isanto"})," for all your help on this!"]}),"\n",(0,s.jsx)(n.h2,{id:"openfga-v143",children:"OpenFGA v1.4.3"}),"\n",(0,s.jsxs)(n.p,{children:["We just shipped OpenFGA ",(0,s.jsx)(n.a,{href:"https://github.com/openfga/openfga/releases/tag/v1.4.3",children:"v1.4.3"}),", with performance improvements and ",(0,s.jsx)(n.a,{href:"https://github.com/openfga/openfga/security/advisories/GHSA-rxpw-85vw-fx87",children:"one security issue"})," fixed. We recommend everyone to upgrade to the latest release."]}),"\n",(0,s.jsx)(n.h2,{id:"sdk-improvements",children:"SDK Improvements"}),"\n",(0,s.jsx)(n.p,{children:"New releases with bug fixes and improvements:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/openfga/java-sdk/releases/tag/v0.3.2",children:"Java SDK v0.3.2"}),". If you are using the Java SDK please upgrade to this version."]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://github.com/openfga/go-sdk/releases/tag/v0.3.4",children:"Go SDK v0.3.4"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/openfga/python-sdk/releases/tag/v0.4.0",children:"Python SDK v0.4.0"}),", which has breaking changes."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Thanks again to ",(0,s.jsx)(n.a,{href:"https://github.com/le-yams",children:"Yann D'Isanto"})," for your help on the Java SDK!"]}),"\n",(0,s.jsx)(n.h2,{id:"language-improvements",children:"Language Improvements"}),"\n",(0,s.jsx)(n.p,{children:"The DSL language now has better support for comments and mixed operator support, where you can use parentheses to group expressions when defining relations:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"DSL improvements",src:i(25584).A+"",width:"1712",height:"858"})}),"\n",(0,s.jsx)(n.p,{children:"It's available in the VS Code extension, the CLI and the Playground."}),"\n",(0,s.jsx)(n.h2,{id:"github-actions",children:"Github Actions"}),"\n",(0,s.jsxs)(n.p,{children:["We shipped a couple of Github Actions that help you deploy FGA models, and run model tests as part of your CI/CD build. Find them ",(0,s.jsx)(n.a,{href:"https://github.com/marketplace?query=openfga",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"whats-next-check-our-rfcs",children:"What's Next? Check our RFCs!"}),"\n",(0,s.jsx)(n.p,{children:"We've been discussing with the OpenFGA community a couple of RFCs that we are planning to implement in the next few weeks:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/openfga/rfcs/pull/14",children:"Support for modular models"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/openfga/rfcs/pull/15",children:"ListUsers API"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Please take a look at them and let us know what you think!"}),"\n",(0,s.jsx)(n.h2,{id:"openfga-community",children:"OpenFGA Community"}),"\n",(0,s.jsx)(n.p,{children:"We have a very welcoming community, and we'd love to have you there! You can join us in different ways:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Join our ",(0,s.jsx)(n.a,{href:"https://github.com/openfga/community/blob/main/community-meetings.md",children:"community meetings"}),", the second Thursday of every month. All the recordings are ",(0,s.jsx)(n.a,{href:"https://www.youtube.com/@OpenFGA",children:"here"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["Stay up to date by following us on ",(0,s.jsx)(n.a,{href:"https://twitter.com/openfga",children:"X"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["Join our ",(0,s.jsx)(n.a,{href:"https://openfga.dev/community",children:"community channels"})," in Slack or GitHub."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"see-you-next-month",children:"See you next month!"}),"\n",(0,s.jsx)(n.p,{children:"Fine Grained News are published every month, after the OpenFGA community meeting. If you have any feedback, you want to share your OpenFGA story, or know about something that you think is worth mentioning, please let us know!"})]})}function c(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},25584:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/fgn-2023-12-language-8a3e7f852814fa536430c8e3f81e57f1.png"},67618:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/fgn-2024-01-team-fdc90c95b67c4a2f60a3235944480b1d.png"},24044:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/fgn-2024-01-vscode-d007f1d2381717433705be88761959e2.gif"},34047:e=>{e.exports=JSON.parse('{"permalink":"/pr-preview/pr-921/blog/fine-grained-news-2024-01","source":"@site/blog/fine-grained-news-2024-01.md","title":"Fine Grained News - January 2024","description":"Fine Grained News","date":"2024-01-29T00:00:00.000Z","tags":[{"inline":true,"label":"newsletter","permalink":"/pr-preview/pr-921/blog/tags/newsletter"}],"readingTime":3.35,"hasTruncateMarker":false,"authors":[{"name":"Andres Aguiar","title":"Product Manager","url":"https://github.com/aaguiarz","imageURL":"/pr-preview/pr-921/img/blog/authors/andres.jpg","key":"aaguiar","page":null}],"frontMatter":{"title":"Fine Grained News - January 2024","description":"Fine Grained News","slug":"fine-grained-news-2024-01","date":"2024-01-29T00:00:00.000Z","authors":"aaguiar","tags":["newsletter"],"image":"https://openfga.dev/img/og-rich-embed.png","hide_table_of_contents":false},"unlisted":false,"prevItem":{"title":"Fine Grained News - February 2024","permalink":"/pr-preview/pr-921/blog/fine-grained-news-2024-02"},"nextItem":{"title":"Fine Grained News - December 2023","permalink":"/pr-preview/pr-921/blog/fine-grained-news-2023-12"}}')}}]);
\ No newline at end of file
diff --git a/pr-preview/pr-921/assets/js/54f0799f.86d470d9.js b/pr-preview/pr-921/assets/js/54f0799f.86d470d9.js
new file mode 100644
index 000000000..0c2bcdb78
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/54f0799f.86d470d9.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkopenfga_dev=self.webpackChunkopenfga_dev||[]).push([[2759],{94254:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>c,frontMatter:()=>r,metadata:()=>i,toc:()=>h});var i=t(37170),a=t(74848),s=t(28453);const r={title:"Fine Grained News - May 2024",description:"Fine Grained News",slug:"fine-grained-news-2024-05",date:new Date("2024-05-30T00:00:00.000Z"),authors:"aaguiar",tags:["newsletter"],image:"https://openfga.dev/img/og-rich-embed.png",hide_table_of_contents:!1},o="Fine Grained News",l={authorsImageUrls:[void 0]},h=[{value:"New Releases!",id:"new-releases",level:2},{value:"What's Next",id:"whats-next",level:2},{value:"OpenFGA @ CloudNative SecurityCon",id:"openfga--cloudnative-securitycon",level:2},{value:"Latest Features",id:"latest-features",level:2},{value:"Transitioning from Discord to CNCF's Slack",id:"transitioning-from-discord-to-cncfs-slack",level:2},{value:"See you next month!",id:"see-you-next-month",level:2}];function d(e){const n={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Welcome to Fine Grained News, May edition!"}),"\n",(0,a.jsx)(n.h2,{id:"new-releases",children:"New Releases!"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["We shipped the ",(0,a.jsx)(n.a,{href:"https://openfga.dev/blog/list-users-announcement",children:"a ListUsers API"}),". ListUsers allows you to retrieve all the users that have a specific relation with a resource (e.g. all users that can view a document)."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["In collaboration with ",(0,a.jsx)(n.a,{href:"https://github.com/yann-disanto",children:"Yann D'Isanto"})," we shipped a ",(0,a.jsx)(n.a,{href:"https://plugins.jetbrains.com/plugin/24394-openfga",children:"plugin for JetBrain's IDEs"})," to allow syntax coloring and validation of OpenFGA models. Together with the ",(0,a.jsx)(n.a,{href:"https://marketplace.visualstudio.com/items?itemName=openfga.openfga-vscode",children:"Visual Studio Code integration"})," and the ",(0,a.jsx)(n.a,{href:"https://github.com/matoous/tree-sitter-fga",children:"Tree sitter grammar"})," from ",(0,a.jsx)(n.a,{href:"https://github.com/matoous/",children:"Matou\u0161 Dzivjak"}),", OpenFGA has get great coverage for major IDEs and editors."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"whats-next",children:"What's Next"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"We've identified a few areas where we can improve performance and we are actively working on them."}),"\n",(0,a.jsxs)(n.li,{children:["We'll be ",(0,a.jsx)(n.a,{href:"https://github.com/openfga/roadmap/issues/41",children:"instrumenting our SDKs"})," to provide metrics / tracing and logging through OpenTelemetry APIs."]}),"\n",(0,a.jsxs)(n.li,{children:["We'll be adding ",(0,a.jsx)(n.a,{href:"https://github.com/openfga/roadmap/issues/54",children:"additional consistency options"})," for OpenFGA query APIs."]}),"\n",(0,a.jsxs)(n.li,{children:["We'll be working on adding ",(0,a.jsx)(n.a,{href:"https://github.com/openfga/roadmap/issues/30",children:"authorization for OpenFGA APIs"}),"."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Please check the items above and let us know if you have any feedback or idea."}),"\n",(0,a.jsx)(n.h2,{id:"openfga--cloudnative-securitycon",children:"OpenFGA @ CloudNative SecurityCon"}),"\n",(0,a.jsxs)(n.p,{children:["OpenFGA will be present in ",(0,a.jsx)(n.a,{href:"https://events.linuxfoundation.org/cloudnativesecuritycon-north-america/",children:"CloudNative SecurityCon North America"}),"!"]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://github.com/miparnisari",children:"Maria Ines Parnisari"})," from the OpenFGA team and ",(0,a.jsx)(n.a,{href:"https://github.com/evankanderson",children:"Evan Anderson"})," from ",(0,a.jsx)(n.a,{href:"https://stacklok.com/",children:"Stacklok"})," will be presenting on ",(0,a.jsx)(n.a,{href:"https://cloudnativesecurityconna24.sched.com/event/1dCVn/implementing-a-multi-tenant-relationship-based-authorization-model-with-openfga-evan-anderson-stacklok-maria-ines-parnisari-okta",children:"Implementing a Multi-Tenant, Relationship-Based Authorization Model with OpenFGA"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"We hope to see you there!"}),"\n",(0,a.jsx)(n.h2,{id:"latest-features",children:"Latest Features"}),"\n",(0,a.jsx)(n.p,{children:"In case you missed them, here are some of the latest major features we've added to OpenFGA:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://openfga.dev/blog/conditional-tuples-announcement",children:"Conditional Tuples"})," allows you to define tuples that are only valid under certain conditions."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://openfga.dev/blog/modular-models-announcement",children:"Modular Models"})," makes it easy for multiple teams to collaborate on a single OpenFGA model."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://openfga.dev/blog/list-users-announcement",children:"List Users API"})," allowing you to retrieve all the users that have a specific relation with a resource."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://github.com/openfga/spring-boot-starter",children:"Spring Boot Starter for OpenFGA"})," simplifies integrating OpenFGA with Spring Security applications."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://plugins.jetbrains.com/plugin/24394-openfga",children:"JetBrain's IDEs plugin"})," to allow syntax coloring and validation of OpenFGA models."]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"transitioning-from-discord-to-cncfs-slack",children:"Transitioning from Discord to CNCF's Slack"}),"\n",(0,a.jsxs)(n.p,{children:["As we mentioned before, we transitioned out from Discord for OpenFGA and are now using the CNCF ",(0,a.jsx)(n.a,{href:"https://cloud-native.slack.com/archives/C06G1NNH47N",children:"#openfga Slack channel"}),". If you are not part of the CNCF Slack workspace, you need to join the ",(0,a.jsx)(n.a,{href:"https://slack.cncf.io",children:"CNCF Slack"})," first."]}),"\n",(0,a.jsxs)(n.p,{children:["Checkout ",(0,a.jsx)(n.a,{href:"https://openfga.dev/community",children:"https://openfga.dev/community"})," for all the places to find us."]}),"\n",(0,a.jsx)(n.h2,{id:"see-you-next-month",children:"See you next month!"}),"\n",(0,a.jsx)(n.p,{children:"Fine Grained News are published every month. If you have any feedback, want to share your OpenFGA story, or know about something that you think is worth mentioning, please let us know!"})]})}function c(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},37170:e=>{e.exports=JSON.parse('{"permalink":"/pr-preview/pr-921/blog/fine-grained-news-2024-05","source":"@site/blog/fine-grained-news-2024-05.md","title":"Fine Grained News - May 2024","description":"Fine Grained News","date":"2024-05-30T00:00:00.000Z","tags":[{"inline":true,"label":"newsletter","permalink":"/pr-preview/pr-921/blog/tags/newsletter"}],"readingTime":1.97,"hasTruncateMarker":false,"authors":[{"name":"Andres Aguiar","title":"Product Manager","url":"https://github.com/aaguiarz","imageURL":"/pr-preview/pr-921/img/blog/authors/andres.jpg","key":"aaguiar","page":null}],"frontMatter":{"title":"Fine Grained News - May 2024","description":"Fine Grained News","slug":"fine-grained-news-2024-05","date":"2024-05-30T00:00:00.000Z","authors":"aaguiar","tags":["newsletter"],"image":"https://openfga.dev/img/og-rich-embed.png","hide_table_of_contents":false},"unlisted":false,"prevItem":{"title":"Fine Grained News - June 2024","permalink":"/pr-preview/pr-921/blog/fine-grained-news-2024-06"},"nextItem":{"title":"List Users API","permalink":"/pr-preview/pr-921/blog/list-users-announcement"}}')}}]);
\ No newline at end of file
diff --git a/pr-preview/pr-921/assets/js/5688.6d48c159.js b/pr-preview/pr-921/assets/js/5688.6d48c159.js
new file mode 100644
index 000000000..112ec33ca
--- /dev/null
+++ b/pr-preview/pr-921/assets/js/5688.6d48c159.js
@@ -0,0 +1,2 @@
+/*! For license information please see 5688.6d48c159.js.LICENSE.txt */
+(self.webpackChunkopenfga_dev=self.webpackChunkopenfga_dev||[]).push([[5688],{69119:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BLANK_URL=t.relativeFirstCharacters=t.whitespaceEscapeCharsRegex=t.urlSchemeRegex=t.ctrlCharactersRegex=t.htmlCtrlEntityRegex=t.htmlEntitiesRegex=t.invalidProtocolRegex=void 0,t.invalidProtocolRegex=/^([^\w]*)(javascript|data|vbscript)/im,t.htmlEntitiesRegex=/(\w+)(^\w|;)?/g,t.htmlCtrlEntityRegex=/&(newline|tab);/gi,t.ctrlCharactersRegex=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,t.urlSchemeRegex=/^.+(:|:)/gim,t.whitespaceEscapeCharsRegex=/(\\|%5[cC])((%(6[eE]|72|74))|[nrt])/g,t.relativeFirstCharacters=[".","/"],t.BLANK_URL="about:blank"},16750:(e,t,n)=>{"use strict";t.J=void 0;var r=n(69119);function s(e){try{return decodeURIComponent(e)}catch(t){return e}}t.J=function(e){if(!e)return r.BLANK_URL;var t,n,o=s(e);do{t=(o=s(o=(n=o,n.replace(r.ctrlCharactersRegex,"").replace(r.htmlEntitiesRegex,(function(e,t){return String.fromCharCode(t)}))).replace(r.htmlCtrlEntityRegex,"").replace(r.ctrlCharactersRegex,"").replace(r.whitespaceEscapeCharsRegex,"").trim())).match(r.ctrlCharactersRegex)||o.match(r.htmlEntitiesRegex)||o.match(r.htmlCtrlEntityRegex)||o.match(r.whitespaceEscapeCharsRegex)}while(t&&t.length>0);var i=o;if(!i)return r.BLANK_URL;if(function(e){return r.relativeFirstCharacters.indexOf(e[0])>-1}(i))return i;var a=i.match(r.urlSchemeRegex);if(!a)return i;var c=a[0];return r.invalidProtocolRegex.test(c)?r.BLANK_URL:i}},78478:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});n(96540);var r=n(92303),s=n(74848);function o(e){let{children:t,fallback:n}=e;return(0,r.A)()?(0,s.jsx)(s.Fragment,{children:t?.()}):n??null}},67526:(e,t)=>{"use strict";t.byteLength=function(e){var t=a(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){var t,n,o=a(e),i=o[0],c=o[1],l=new s(function(e,t,n){return 3*(t+n)/4-n}(0,i,c)),u=0,p=c>0?i-4:i;for(n=0;n>16&255,l[u++]=t>>8&255,l[u++]=255&t;2===c&&(t=r[e.charCodeAt(n)]<<2|r[e.charCodeAt(n+1)]>>4,l[u++]=255&t);1===c&&(t=r[e.charCodeAt(n)]<<10|r[e.charCodeAt(n+1)]<<4|r[e.charCodeAt(n+2)]>>2,l[u++]=t>>8&255,l[u++]=255&t);return l},t.fromByteArray=function(e){for(var t,r=e.length,s=r%3,o=[],i=16383,a=0,l=r-s;al?l:a+i));1===s?(t=e[r-1],o.push(n[t>>2]+n[t<<4&63]+"==")):2===s&&(t=(e[r-2]<<8)+e[r-1],o.push(n[t>>10]+n[t>>4&63]+n[t<<2&63]+"="));return o.join("")};for(var n=[],r=[],s="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0;i<64;++i)n[i]=o[i],r[o.charCodeAt(i)]=i;function a(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function c(e,t,r){for(var s,o,i=[],a=t;a>18&63]+n[o>>12&63]+n[o>>6&63]+n[63&o]);return i.join("")}r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63},17965:(e,t,n)=>{"use strict";var r=n(16426),s={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var n,o,i,a,c,l,u=!1;t||(t={}),n=t.debug||!1;try{if(i=r(),a=document.createRange(),c=document.getSelection(),(l=document.createElement("span")).textContent=e,l.ariaHidden="true",l.style.all="unset",l.style.position="fixed",l.style.top=0,l.style.clip="rect(0, 0, 0, 0)",l.style.whiteSpace="pre",l.style.webkitUserSelect="text",l.style.MozUserSelect="text",l.style.msUserSelect="text",l.style.userSelect="text",l.addEventListener("copy",(function(r){if(r.stopPropagation(),t.format)if(r.preventDefault(),void 0===r.clipboardData){n&&console.warn("unable to use e.clipboardData"),n&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var o=s[t.format]||s.default;window.clipboardData.setData(o,e)}else r.clipboardData.clearData(),r.clipboardData.setData(t.format,e);t.onCopy&&(r.preventDefault(),t.onCopy(r.clipboardData))})),document.body.appendChild(l),a.selectNodeContents(l),c.addRange(a),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");u=!0}catch(p){n&&console.error("unable to copy using execCommand: ",p),n&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),u=!0}catch(p){n&&console.error("unable to copy using clipboardData: ",p),n&&console.error("falling back to prompt"),o=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"\u2318":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in t?t.message:"Copy to clipboard: #{key}, Enter"),window.prompt(o,e)}}finally{c&&("function"==typeof c.removeRange?c.removeRange(a):c.removeAllRanges()),l&&document.body.removeChild(l),i()}return u}},2205:function(e,t,n){var r;r=void 0!==n.g?n.g:this,e.exports=function(e){if(e.CSS&&e.CSS.escape)return e.CSS.escape;var t=function(e){if(0==arguments.length)throw new TypeError("`CSS.escape` requires an argument.");for(var t,n=String(e),r=n.length,s=-1,o="",i=n.charCodeAt(0);++s=1&&t<=31||127==t||0==s&&t>=48&&t<=57||1==s&&t>=48&&t<=57&&45==i?"\\"+t.toString(16)+" ":0==s&&1==r&&45==t||!(t>=128||45==t||95==t||t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122)?"\\"+n.charAt(s):n.charAt(s):o+="\ufffd";return o};return e.CSS||(e.CSS={}),e.CSS.escape=t,t}(r)},42838:function(e){e.exports=function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:r,getOwnPropertyDescriptor:s}=Object;let{freeze:o,seal:i,create:a}=Object,{apply:c,construct:l}="undefined"!=typeof Reflect&&Reflect;o||(o=function(e){return e}),i||(i=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),l||(l=function(e,t){return new e(...t)});const u=x(Array.prototype.forEach),p=x(Array.prototype.pop),h=x(Array.prototype.push),d=x(String.prototype.toLowerCase),f=x(String.prototype.toString),m=x(String.prototype.match),g=x(String.prototype.replace),y=x(String.prototype.indexOf),v=x(String.prototype.trim),b=x(Object.prototype.hasOwnProperty),E=x(RegExp.prototype.test),w=S(TypeError);function x(e){return function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),s=1;s2&&void 0!==arguments[2]?arguments[2]:d;t&&t(e,null);let o=r.length;for(;o--;){let t=r[o];if("string"==typeof t){const e=s(t);e!==t&&(n(r)||(r[o]=e),t=e)}e[t]=!0}return e}function A(e){for(let t=0;t/gm),q=i(/\${[\w\W]*}/gm),U=i(/^data-[\-\w.\u00B7-\uFFFF]/),z=i(/^aria-[\-\w]+$/),V=i(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),K=i(/^(?:\w+script|data):/i),J=i(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),W=i(/^html$/i),H=i(/^[a-z][.\w]*(-[.\w]+)+$/i);var G=Object.freeze({__proto__:null,MUSTACHE_EXPR:B,ERB_EXPR:L,TMPLIT_EXPR:q,DATA_ATTR:U,ARIA_ATTR:z,IS_ALLOWED_URI:V,IS_SCRIPT_OR_DATA:K,ATTR_WHITESPACE:J,DOCTYPE_NAME:W,CUSTOM_ELEMENT:H});const Y={element:1,attribute:2,text:3,cdataSection:4,entityReference:5,entityNode:6,progressingInstruction:7,comment:8,document:9,documentType:10,documentFragment:11,notation:12},X=function(){return"undefined"==typeof window?null:window},Z=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const r="data-tt-policy-suffix";t&&t.hasAttribute(r)&&(n=t.getAttribute(r));const s="dompurify"+(n?"#"+n:"");try{return e.createPolicy(s,{createHTML:e=>e,createScriptURL:e=>e})}catch(o){return console.warn("TrustedTypes policy "+s+" could not be created."),null}};function Q(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:X();const n=e=>Q(e);if(n.version="3.1.6",n.removed=[],!t||!t.document||t.document.nodeType!==Y.document)return n.isSupported=!1,n;let{document:r}=t;const s=r,i=s.currentScript,{DocumentFragment:c,HTMLTemplateElement:l,Node:x,Element:S,NodeFilter:A,NamedNodeMap:B=t.NamedNodeMap||t.MozNamedAttrMap,HTMLFormElement:L,DOMParser:q,trustedTypes:U}=t,z=S.prototype,K=C(z,"cloneNode"),J=C(z,"remove"),H=C(z,"nextSibling"),ee=C(z,"childNodes"),te=C(z,"parentNode");if("function"==typeof l){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let ne,re="";const{implementation:se,createNodeIterator:oe,createDocumentFragment:ie,getElementsByTagName:ae}=r,{importNode:ce}=s;let le={};n.isSupported="function"==typeof e&&"function"==typeof te&&se&&void 0!==se.createHTMLDocument;const{MUSTACHE_EXPR:ue,ERB_EXPR:pe,TMPLIT_EXPR:he,DATA_ATTR:de,ARIA_ATTR:fe,IS_SCRIPT_OR_DATA:me,ATTR_WHITESPACE:ge,CUSTOM_ELEMENT:ye}=G;let{IS_ALLOWED_URI:ve}=G,be=null;const Ee=_({},[...k,...j,...N,...P,...M]);let we=null;const xe=_({},[...R,...D,...$,...F]);let Se=Object.seal(a(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),_e=null,Ae=null,Oe=!0,Ce=!0,ke=!1,je=!0,Ne=!1,Ie=!0,Pe=!1,Te=!1,Me=!1,Re=!1,De=!1,$e=!1,Fe=!0,Be=!1;const Le="user-content-";let qe=!0,Ue=!1,ze={},Ve=null;const Ke=_({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Je=null;const We=_({},["audio","video","img","source","image","track"]);let He=null;const Ge=_({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Ye="http://www.w3.org/1998/Math/MathML",Xe="http://www.w3.org/2000/svg",Ze="http://www.w3.org/1999/xhtml";let Qe=Ze,et=!1,tt=null;const nt=_({},[Ye,Xe,Ze],f);let rt=null;const st=["application/xhtml+xml","text/html"],ot="text/html";let it=null,at=null;const ct=r.createElement("form"),lt=function(e){return e instanceof RegExp||e instanceof Function},ut=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!at||at!==e){if(e&&"object"==typeof e||(e={}),e=O(e),rt=-1===st.indexOf(e.PARSER_MEDIA_TYPE)?ot:e.PARSER_MEDIA_TYPE,it="application/xhtml+xml"===rt?f:d,be=b(e,"ALLOWED_TAGS")?_({},e.ALLOWED_TAGS,it):Ee,we=b(e,"ALLOWED_ATTR")?_({},e.ALLOWED_ATTR,it):xe,tt=b(e,"ALLOWED_NAMESPACES")?_({},e.ALLOWED_NAMESPACES,f):nt,He=b(e,"ADD_URI_SAFE_ATTR")?_(O(Ge),e.ADD_URI_SAFE_ATTR,it):Ge,Je=b(e,"ADD_DATA_URI_TAGS")?_(O(We),e.ADD_DATA_URI_TAGS,it):We,Ve=b(e,"FORBID_CONTENTS")?_({},e.FORBID_CONTENTS,it):Ke,_e=b(e,"FORBID_TAGS")?_({},e.FORBID_TAGS,it):{},Ae=b(e,"FORBID_ATTR")?_({},e.FORBID_ATTR,it):{},ze=!!b(e,"USE_PROFILES")&&e.USE_PROFILES,Oe=!1!==e.ALLOW_ARIA_ATTR,Ce=!1!==e.ALLOW_DATA_ATTR,ke=e.ALLOW_UNKNOWN_PROTOCOLS||!1,je=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,Ne=e.SAFE_FOR_TEMPLATES||!1,Ie=!1!==e.SAFE_FOR_XML,Pe=e.WHOLE_DOCUMENT||!1,Re=e.RETURN_DOM||!1,De=e.RETURN_DOM_FRAGMENT||!1,$e=e.RETURN_TRUSTED_TYPE||!1,Me=e.FORCE_BODY||!1,Fe=!1!==e.SANITIZE_DOM,Be=e.SANITIZE_NAMED_PROPS||!1,qe=!1!==e.KEEP_CONTENT,Ue=e.IN_PLACE||!1,ve=e.ALLOWED_URI_REGEXP||V,Qe=e.NAMESPACE||Ze,Se=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&<(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Se.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&<(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Se.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Se.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Ne&&(Ce=!1),De&&(Re=!0),ze&&(be=_({},M),we=[],!0===ze.html&&(_(be,k),_(we,R)),!0===ze.svg&&(_(be,j),_(we,D),_(we,F)),!0===ze.svgFilters&&(_(be,N),_(we,D),_(we,F)),!0===ze.mathMl&&(_(be,P),_(we,$),_(we,F))),e.ADD_TAGS&&(be===Ee&&(be=O(be)),_(be,e.ADD_TAGS,it)),e.ADD_ATTR&&(we===xe&&(we=O(we)),_(we,e.ADD_ATTR,it)),e.ADD_URI_SAFE_ATTR&&_(He,e.ADD_URI_SAFE_ATTR,it),e.FORBID_CONTENTS&&(Ve===Ke&&(Ve=O(Ve)),_(Ve,e.FORBID_CONTENTS,it)),qe&&(be["#text"]=!0),Pe&&_(be,["html","head","body"]),be.table&&(_(be,["tbody"]),delete _e.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw w('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw w('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');ne=e.TRUSTED_TYPES_POLICY,re=ne.createHTML("")}else void 0===ne&&(ne=Z(U,i)),null!==ne&&"string"==typeof re&&(re=ne.createHTML(""));o&&o(e),at=e}},pt=_({},["mi","mo","mn","ms","mtext"]),ht=_({},["foreignobject","annotation-xml"]),dt=_({},["title","style","font","a","script"]),ft=_({},[...j,...N,...I]),mt=_({},[...P,...T]),gt=function(e){let t=te(e);t&&t.tagName||(t={namespaceURI:Qe,tagName:"template"});const n=d(e.tagName),r=d(t.tagName);return!!tt[e.namespaceURI]&&(e.namespaceURI===Xe?t.namespaceURI===Ze?"svg"===n:t.namespaceURI===Ye?"svg"===n&&("annotation-xml"===r||pt[r]):Boolean(ft[n]):e.namespaceURI===Ye?t.namespaceURI===Ze?"math"===n:t.namespaceURI===Xe?"math"===n&&ht[r]:Boolean(mt[n]):e.namespaceURI===Ze?!(t.namespaceURI===Xe&&!ht[r])&&!(t.namespaceURI===Ye&&!pt[r])&&!mt[n]&&(dt[n]||!ft[n]):!("application/xhtml+xml"!==rt||!tt[e.namespaceURI]))},yt=function(e){h(n.removed,{element:e});try{te(e).removeChild(e)}catch(t){J(e)}},vt=function(e,t){try{h(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(r){h(n.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!we[e])if(Re||De)try{yt(t)}catch(r){}else try{t.setAttribute(e,"")}catch(r){}},bt=function(e){let t=null,n=null;if(Me)e=""+e;else{const t=m(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===rt&&Qe===Ze&&(e=''+e+"");const s=ne?ne.createHTML(e):e;if(Qe===Ze)try{t=(new q).parseFromString(s,rt)}catch(i){}if(!t||!t.documentElement){t=se.createDocument(Qe,"template",null);try{t.documentElement.innerHTML=et?re:s}catch(i){}}const o=t.body||t.documentElement;return e&&n&&o.insertBefore(r.createTextNode(n),o.childNodes[0]||null),Qe===Ze?ae.call(t,Pe?"html":"body")[0]:Pe?t.documentElement:o},Et=function(e){return oe.call(e.ownerDocument||e,e,A.SHOW_ELEMENT|A.SHOW_COMMENT|A.SHOW_TEXT|A.SHOW_PROCESSING_INSTRUCTION|A.SHOW_CDATA_SECTION,null)},wt=function(e){return e instanceof L&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof B)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},xt=function(e){return"function"==typeof x&&e instanceof x},St=function(e,t,r){le[e]&&u(le[e],(e=>{e.call(n,t,r,at)}))},_t=function(e){let t=null;if(St("beforeSanitizeElements",e,null),wt(e))return yt(e),!0;const r=it(e.nodeName);if(St("uponSanitizeElement",e,{tagName:r,allowedTags:be}),e.hasChildNodes()&&!xt(e.firstElementChild)&&E(/<[/\w]/g,e.innerHTML)&&E(/<[/\w]/g,e.textContent))return yt(e),!0;if(e.nodeType===Y.progressingInstruction)return yt(e),!0;if(Ie&&e.nodeType===Y.comment&&E(/<[/\w]/g,e.data))return yt(e),!0;if(!be[r]||_e[r]){if(!_e[r]&&Ot(r)){if(Se.tagNameCheck instanceof RegExp&&E(Se.tagNameCheck,r))return!1;if(Se.tagNameCheck instanceof Function&&Se.tagNameCheck(r))return!1}if(qe&&!Ve[r]){const t=te(e)||e.parentNode,n=ee(e)||e.childNodes;if(n&&t)for(let r=n.length-1;r>=0;--r){const s=K(n[r],!0);s.__removalCount=(e.__removalCount||0)+1,t.insertBefore(s,H(e))}}return yt(e),!0}return e instanceof S&&!gt(e)?(yt(e),!0):"noscript"!==r&&"noembed"!==r&&"noframes"!==r||!E(/<\/no(script|embed|frames)/i,e.innerHTML)?(Ne&&e.nodeType===Y.text&&(t=e.textContent,u([ue,pe,he],(e=>{t=g(t,e," ")})),e.textContent!==t&&(h(n.removed,{element:e.cloneNode()}),e.textContent=t)),St("afterSanitizeElements",e,null),!1):(yt(e),!0)},At=function(e,t,n){if(Fe&&("id"===t||"name"===t)&&(n in r||n in ct))return!1;if(Ce&&!Ae[t]&&E(de,t));else if(Oe&&E(fe,t));else if(!we[t]||Ae[t]){if(!(Ot(e)&&(Se.tagNameCheck instanceof RegExp&&E(Se.tagNameCheck,e)||Se.tagNameCheck instanceof Function&&Se.tagNameCheck(e))&&(Se.attributeNameCheck instanceof RegExp&&E(Se.attributeNameCheck,t)||Se.attributeNameCheck instanceof Function&&Se.attributeNameCheck(t))||"is"===t&&Se.allowCustomizedBuiltInElements&&(Se.tagNameCheck instanceof RegExp&&E(Se.tagNameCheck,n)||Se.tagNameCheck instanceof Function&&Se.tagNameCheck(n))))return!1}else if(He[t]);else if(E(ve,g(n,ge,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==y(n,"data:")||!Je[e])if(ke&&!E(me,g(n,ge,"")));else if(n)return!1;return!0},Ot=function(e){return"annotation-xml"!==e&&m(e,ye)},Ct=function(e){St("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const r={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:we};let s=t.length;for(;s--;){const i=t[s],{name:a,namespaceURI:c,value:l}=i,h=it(a);let d="value"===a?l:v(l);if(r.attrName=h,r.attrValue=d,r.keepAttr=!0,r.forceKeepAttr=void 0,St("uponSanitizeAttribute",e,r),d=r.attrValue,Ie&&E(/((--!?|])>)|<\/(style|title)/i,d)){vt(a,e);continue}if(r.forceKeepAttr)continue;if(vt(a,e),!r.keepAttr)continue;if(!je&&E(/\/>/i,d)){vt(a,e);continue}Ne&&u([ue,pe,he],(e=>{d=g(d,e," ")}));const f=it(e.nodeName);if(At(f,h,d)){if(!Be||"id"!==h&&"name"!==h||(vt(a,e),d=Le+d),ne&&"object"==typeof U&&"function"==typeof U.getAttributeType)if(c);else switch(U.getAttributeType(f,h)){case"TrustedHTML":d=ne.createHTML(d);break;case"TrustedScriptURL":d=ne.createScriptURL(d)}try{c?e.setAttributeNS(c,a,d):e.setAttribute(a,d),wt(e)?yt(e):p(n.removed)}catch(o){}}}St("afterSanitizeAttributes",e,null)},kt=function e(t){let n=null;const r=Et(t);for(St("beforeSanitizeShadowDOM",t,null);n=r.nextNode();)St("uponSanitizeShadowNode",n,null),_t(n)||(n.content instanceof c&&e(n.content),Ct(n));St("afterSanitizeShadowDOM",t,null)};return n.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=null,o=null,i=null,a=null;if(et=!e,et&&(e="\x3c!--\x3e"),"string"!=typeof e&&!xt(e)){if("function"!=typeof e.toString)throw w("toString is not a function");if("string"!=typeof(e=e.toString()))throw w("dirty is not a string, aborting")}if(!n.isSupported)return e;if(Te||ut(t),n.removed=[],"string"==typeof e&&(Ue=!1),Ue){if(e.nodeName){const t=it(e.nodeName);if(!be[t]||_e[t])throw w("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof x)r=bt("\x3c!----\x3e"),o=r.ownerDocument.importNode(e,!0),o.nodeType===Y.element&&"BODY"===o.nodeName||"HTML"===o.nodeName?r=o:r.appendChild(o);else{if(!Re&&!Ne&&!Pe&&-1===e.indexOf("<"))return ne&&$e?ne.createHTML(e):e;if(r=bt(e),!r)return Re?null:$e?re:""}r&&Me&&yt(r.firstChild);const l=Et(Ue?e:r);for(;i=l.nextNode();)_t(i)||(i.content instanceof c&&kt(i.content),Ct(i));if(Ue)return e;if(Re){if(De)for(a=ie.call(r.ownerDocument);r.firstChild;)a.appendChild(r.firstChild);else a=r;return(we.shadowroot||we.shadowrootmode)&&(a=ce.call(s,a,!0)),a}let p=Pe?r.outerHTML:r.innerHTML;return Pe&&be["!doctype"]&&r.ownerDocument&&r.ownerDocument.doctype&&r.ownerDocument.doctype.name&&E(W,r.ownerDocument.doctype.name)&&(p="\n"+p),Ne&&u([ue,pe,he],(e=>{p=g(p,e," ")})),ne&&$e?ne.createHTML(p):p},n.setConfig=function(){ut(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Te=!0},n.clearConfig=function(){at=null,Te=!1},n.isValidAttribute=function(e,t,n){at||ut({});const r=it(e),s=it(t);return At(r,s,n)},n.addHook=function(e,t){"function"==typeof t&&(le[e]=le[e]||[],h(le[e],t))},n.removeHook=function(e){if(le[e])return p(le[e])},n.removeHooks=function(e){le[e]&&(le[e]=[])},n.removeAllHooks=function(){le={}},n}return Q()}()},78004:e=>{"use strict";class t{constructor(e,t){this.low=e,this.high=t,this.length=1+t-e}overlaps(e){return!(this.highe.high)}touches(e){return!(this.high+1e.high)}add(e){return new t(Math.min(this.low,e.low),Math.max(this.high,e.high))}subtract(e){return e.low<=this.low&&e.high>=this.high?[]:e.low>this.low&&e.highe+t.length),0)}add(e,r){var s=e=>{for(var t=0;t{for(var t=0;t{for(var n=0;n{for(var n=t.low;n<=t.high;)e.push(n),n++;return e}),[])}subranges(){return this.ranges.map((e=>({low:e.low,high:e.high,length:1+e.high-e.low})))}}e.exports=n},26311:e=>{!function(){var t;function n(e){for(var t,n,r,s,o=1,i=[].slice.call(arguments),a=0,c=e.length,l="",u=!1,p=!1,h=function(){return i[o++]},d=function(){for(var n="";/\d/.test(e[a]);)n+=e[a++],t=e[a];return n.length>0?parseInt(n):null};a{function t(e){return e instanceof Map?e.clear=e.delete=e.set=function(){throw new Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=function(){throw new Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((function(n){var r=e[n];"object"!=typeof r||Object.isFrozen(r)||t(r)})),e}var n=t,r=t;n.default=r;class s{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function o(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function i(e,...t){const n=Object.create(null);for(const r in e)n[r]=e[r];return t.forEach((function(e){for(const t in e)n[t]=e[t]})),n}const a=e=>!!e.kind;class c{constructor(e,t){this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){this.buffer+=o(e)}openNode(e){if(!a(e))return;let t=e.kind;e.sublanguage||(t=`${this.classPrefix}${t}`),this.span(t)}closeNode(e){a(e)&&(this.buffer+="")}value(){return this.buffer}span(e){this.buffer+=``}}class l{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const t={kind:e,children:[]};this.add(t),this.stack.push(t)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t),t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{l._collapse(e)})))}}class u extends l{constructor(e){super(),this.options=e}addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){return new c(this,this.options).value()}finalize(){return!0}}function p(e){return e?"string"==typeof e?e:e.source:null}const h=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;const d="[a-zA-Z]\\w*",f="[a-zA-Z_]\\w*",m="\\b\\d+(\\.\\d+)?",g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",y="\\b(0b[01]+)",v={begin:"\\\\[\\s\\S]",relevance:0},b={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[v]},E={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[v]},w={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},x=function(e,t,n={}){const r=i({className:"comment",begin:e,end:t,contains:[]},n);return r.contains.push(w),r.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),r},S=x("//","$"),_=x("/\\*","\\*/"),A=x("#","$"),O={className:"number",begin:m,relevance:0},C={className:"number",begin:g,relevance:0},k={className:"number",begin:y,relevance:0},j={className:"number",begin:m+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},N={begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[v,{begin:/\[/,end:/\]/,relevance:0,contains:[v]}]}]},I={className:"title",begin:d,relevance:0},P={className:"title",begin:f,relevance:0},T={begin:"\\.\\s*"+f,relevance:0};var M=Object.freeze({__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:d,UNDERSCORE_IDENT_RE:f,NUMBER_RE:m,C_NUMBER_RE:g,BINARY_NUMBER_RE:y,RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const t=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map((e=>p(e))).join("")}(t,/.*\b/,e.binary,/\b.*/)),i({className:"meta",begin:t,end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)},BACKSLASH_ESCAPE:v,APOS_STRING_MODE:b,QUOTE_STRING_MODE:E,PHRASAL_WORDS_MODE:w,COMMENT:x,C_LINE_COMMENT_MODE:S,C_BLOCK_COMMENT_MODE:_,HASH_COMMENT_MODE:A,NUMBER_MODE:O,C_NUMBER_MODE:C,BINARY_NUMBER_MODE:k,CSS_NUMBER_MODE:j,REGEXP_MODE:N,TITLE_MODE:I,UNDERSCORE_TITLE_MODE:P,METHOD_GUARD:T,END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{t.data._beginMatch!==e[1]&&t.ignoreMatch()}})}});function R(e,t){"."===e.input[e.index-1]&&t.ignoreMatch()}function D(e,t){t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=R,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,void 0===e.relevance&&(e.relevance=0))}function $(e,t){Array.isArray(e.illegal)&&(e.illegal=function(...e){return"("+e.map((e=>p(e))).join("|")+")"}(...e.illegal))}function F(e,t){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function B(e,t){void 0===e.relevance&&(e.relevance=1)}const L=["of","and","for","in","not","or","if","then","parent","list","value"],q="keyword";function U(e,t,n=q){const r={};return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((function(n){Object.assign(r,U(e[n],t,n))})),r;function s(e,n){t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((function(t){const n=t.split("|");r[n[0]]=[e,z(n[0],n[1])]}))}}function z(e,t){return t?Number(t):function(e){return L.includes(e.toLowerCase())}(e)?0:1}function V(e,{plugins:t}){function n(t,n){return new RegExp(p(t),"m"+(e.case_insensitive?"i":"")+(n?"g":""))}class r{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,t){t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]),this.matchAt+=function(e){return new RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map((e=>e[1]));this.matcherRe=n(function(e,t="|"){let n=0;return e.map((e=>{n+=1;const t=n;let r=p(e),s="";for(;r.length>0;){const e=h.exec(r);if(!e){s+=r;break}s+=r.substring(0,e.index),r=r.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+String(Number(e[1])+t):(s+=e[0],"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const t=this.matcherRe.exec(e);if(!t)return null;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),r=this.matchIndexes[n];return t.splice(0,n),Object.assign(t,r)}}class s{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const t=new r;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))),t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex;let n=t.exec(e);if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)}return n&&(this.regexIndex+=n.position+1,this.regexIndex===this.count&&this.considerAll()),n}}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=i(e.classNameAliases||{}),function t(r,o){const a=r;if(r.isCompiled)return a;[F].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))),r.__beforeBegin=null,[D,$,B].forEach((e=>e(r,o))),r.isCompiled=!0;let c=null;if("object"==typeof r.keywords&&(c=r.keywords.$pattern,delete r.keywords.$pattern),r.keywords&&(r.keywords=U(r.keywords,e.case_insensitive)),r.lexemes&&c)throw new Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return c=c||r.lexemes||/\w+/,a.keywordPatternRe=n(c,!0),o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=n(r.begin),r.endSameAsBegin&&(r.end=r.begin),r.end||r.endsWithParent||(r.end=/\B|\b/),r.end&&(a.endRe=n(r.end)),a.terminatorEnd=p(r.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)),r.illegal&&(a.illegalRe=n(r.illegal)),r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((function(e){return function(e){e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((function(t){return i(e,{variants:null},t)})));if(e.cachedVariants)return e.cachedVariants;if(K(e))return i(e,{starts:e.starts?i(e.starts):null});if(Object.isFrozen(e))return i(e);return e}("self"===e?r:e)}))),r.contains.forEach((function(e){t(e,a)})),r.starts&&t(r.starts,o),a.matcher=function(e){const t=new s;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin"}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end"}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t}(a),a}(e)}function K(e){return!!e&&(e.endsWithParent||K(e.starts))}function J(e){const t={props:["language","code","autodetect"],data:function(){return{detectedLanguage:"",unknownLanguage:!1}},computed:{className(){return this.unknownLanguage?"":"hljs "+this.detectedLanguage},highlighted(){if(!this.autoDetect&&!e.getLanguage(this.language))return console.warn(`The language "${this.language}" you specified could not be found.`),this.unknownLanguage=!0,o(this.code);let t={};return this.autoDetect?(t=e.highlightAuto(this.code),this.detectedLanguage=t.language):(t=e.highlight(this.language,this.code,this.ignoreIllegals),this.detectedLanguage=this.language),t.value},autoDetect(){return!this.language||(e=this.autodetect,Boolean(e||""===e));var e},ignoreIllegals:()=>!0},render(e){return e("pre",{},[e("code",{class:this.className,domProps:{innerHTML:this.highlighted}})])}};return{Component:t,VuePlugin:{install(e){e.component("highlightjs",t)}}}}const W={"after:highlightElement":({el:e,result:t,text:n})=>{const r=G(e);if(!r.length)return;const s=document.createElement("div");s.innerHTML=t.value,t.value=function(e,t,n){let r=0,s="";const i=[];function a(){return e.length&&t.length?e[0].offset!==t[0].offset?e[0].offset"}function l(e){s+=""+H(e)+">"}function u(e){("start"===e.event?c:l)(e.node)}for(;e.length||t.length;){let t=a();if(s+=o(n.substring(r,t[0].offset)),r=t[0].offset,t===e){i.reverse().forEach(l);do{u(t.splice(0,1)[0]),t=a()}while(t===e&&t.length&&t[0].offset===r);i.reverse().forEach(c)}else"start"===t[0].event?i.push(t[0].node):i.pop(),u(t.splice(0,1)[0])}return s+o(n.substr(r))}(r,G(s),n)}};function H(e){return e.nodeName.toLowerCase()}function G(e){const t=[];return function e(n,r){for(let s=n.firstChild;s;s=s.nextSibling)3===s.nodeType?r+=s.nodeValue.length:1===s.nodeType&&(t.push({event:"start",offset:r,node:s}),r=e(s,r),H(s).match(/br|hr|img|input/)||t.push({event:"stop",offset:r,node:s}));return r}(e,0),t}const Y={},X=e=>{console.error(e)},Z=(e,...t)=>{console.log(`WARN: ${e}`,...t)},Q=(e,t)=>{Y[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),Y[`${e}/${t}`]=!0)},ee=o,te=i,ne=Symbol("nomatch");var re=function(e){const t=Object.create(null),r=Object.create(null),o=[];let i=!0;const a=/(^(<[^>]+>|\t|)+|\n)/gm,c="Could not find the language '{}', did you forget to load/include a language module?",l={disableAutodetect:!0,name:"Plain text",contains:[]};let p={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function h(e){return p.noHighlightRe.test(e)}function d(e,t,n,r){let s="",o="";"object"==typeof t?(s=e,n=t.ignoreIllegals,o=t.language,r=void 0):(Q("10.7.0","highlight(lang, code, ...args) has been deprecated."),Q("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),o=e,s=t);const i={code:s,language:o};O("before:highlight",i);const a=i.result?i.result:f(i.language,i.code,n,r);return a.code=i.code,O("after:highlight",a),a}function f(e,n,r,a){function l(e,t){const n=w.case_insensitive?t[0].toLowerCase():t[0];return Object.prototype.hasOwnProperty.call(e.keywords,n)&&e.keywords[n]}function u(){null!=A.subLanguage?function(){if(""===k)return;let e=null;if("string"==typeof A.subLanguage){if(!t[A.subLanguage])return void C.addText(k);e=f(A.subLanguage,k,!0,O[A.subLanguage]),O[A.subLanguage]=e.top}else e=m(k,A.subLanguage.length?A.subLanguage:null);A.relevance>0&&(j+=e.relevance),C.addSublanguage(e.emitter,e.language)}():function(){if(!A.keywords)return void C.addText(k);let e=0;A.keywordPatternRe.lastIndex=0;let t=A.keywordPatternRe.exec(k),n="";for(;t;){n+=k.substring(e,t.index);const r=l(A,t);if(r){const[e,s]=r;if(C.addText(n),n="",j+=s,e.startsWith("_"))n+=t[0];else{const n=w.classNameAliases[e]||e;C.addKeyword(t[0],n)}}else n+=t[0];e=A.keywordPatternRe.lastIndex,t=A.keywordPatternRe.exec(k)}n+=k.substr(e),C.addText(n)}(),k=""}function h(e){return e.className&&C.openNode(w.classNameAliases[e.className]||e.className),A=Object.create(e,{parent:{value:A}}),A}function d(e,t,n){let r=function(e,t){const n=e&&e.exec(t);return n&&0===n.index}(e.endRe,n);if(r){if(e["on:end"]){const n=new s(e);e["on:end"](t,n),n.isMatchIgnored&&(r=!1)}if(r){for(;e.endsParent&&e.parent;)e=e.parent;return e}}if(e.endsWithParent)return d(e.parent,t,n)}function g(e){return 0===A.matcher.regexIndex?(k+=e[0],1):(P=!0,0)}function y(e){const t=e[0],n=e.rule,r=new s(n),o=[n.__beforeBegin,n["on:begin"]];for(const s of o)if(s&&(s(e,r),r.isMatchIgnored))return g(t);return n&&n.endSameAsBegin&&(n.endRe=new RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),n.skip?k+=t:(n.excludeBegin&&(k+=t),u(),n.returnBegin||n.excludeBegin||(k=t)),h(n),n.returnBegin?0:t.length}function v(e){const t=e[0],r=n.substr(e.index),s=d(A,e,r);if(!s)return ne;const o=A;o.skip?k+=t:(o.returnEnd||o.excludeEnd||(k+=t),u(),o.excludeEnd&&(k=t));do{A.className&&C.closeNode(),A.skip||A.subLanguage||(j+=A.relevance),A=A.parent}while(A!==s.parent);return s.starts&&(s.endSameAsBegin&&(s.starts.endRe=s.endRe),h(s.starts)),o.returnEnd?0:t.length}let b={};function E(t,s){const o=s&&s[0];if(k+=t,null==o)return u(),0;if("begin"===b.type&&"end"===s.type&&b.index===s.index&&""===o){if(k+=n.slice(s.index,s.index+1),!i){const t=new Error("0 width match regex");throw t.languageName=e,t.badRule=b.rule,t}return 1}if(b=s,"begin"===s.type)return y(s);if("illegal"===s.type&&!r){const e=new Error('Illegal lexeme "'+o+'" for mode "'+(A.className||"")+'"');throw e.mode=A,e}if("end"===s.type){const e=v(s);if(e!==ne)return e}if("illegal"===s.type&&""===o)return 1;if(I>1e5&&I>3*s.index){throw new Error("potential infinite loop, way more iterations than matches")}return k+=o,o.length}const w=S(e);if(!w)throw X(c.replace("{}",e)),new Error('Unknown language: "'+e+'"');const x=V(w,{plugins:o});let _="",A=a||x;const O={},C=new p.__emitter(p);!function(){const e=[];for(let t=A;t!==w;t=t.parent)t.className&&e.unshift(t.className);e.forEach((e=>C.openNode(e)))}();let k="",j=0,N=0,I=0,P=!1;try{for(A.matcher.considerAll();;){I++,P?P=!1:A.matcher.considerAll(),A.matcher.lastIndex=N;const e=A.matcher.exec(n);if(!e)break;const t=E(n.substring(N,e.index),e);N=e.index+t}return E(n.substr(N)),C.closeAllNodes(),C.finalize(),_=C.toHTML(),{relevance:Math.floor(j),value:_,language:e,illegal:!1,emitter:C,top:A}}catch(T){if(T.message&&T.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:T.message,context:n.slice(N-100,N+100),mode:T.mode},sofar:_,relevance:0,value:ee(n),emitter:C};if(i)return{illegal:!1,relevance:0,value:ee(n),emitter:C,language:e,top:A,errorRaised:T};throw T}}function m(e,n){n=n||p.languages||Object.keys(t);const r=function(e){const t={relevance:0,emitter:new p.__emitter(p),value:ee(e),illegal:!1,top:l};return t.emitter.addText(e),t}(e),s=n.filter(S).filter(A).map((t=>f(t,e,!1)));s.unshift(r);const o=s.sort(((e,t)=>{if(e.relevance!==t.relevance)return t.relevance-e.relevance;if(e.language&&t.language){if(S(e.language).supersetOf===t.language)return 1;if(S(t.language).supersetOf===e.language)return-1}return 0})),[i,a]=o,c=i;return c.second_best=a,c}const g={"before:highlightElement":({el:e})=>{p.useBR&&(e.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/
/g,"\n"))},"after:highlightElement":({result:e})=>{p.useBR&&(e.value=e.value.replace(/\n/g,"
"))}},y=/^(<[^>]+>|\t)+/gm,v={"after:highlightElement":({result:e})=>{p.tabReplace&&(e.value=e.value.replace(y,(e=>e.replace(/\t/g,p.tabReplace))))}};function b(e){let t=null;const n=function(e){let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"";const n=p.languageDetectRe.exec(t);if(n){const t=S(n[1]);return t||(Z(c.replace("{}",n[1])),Z("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"}return t.split(/\s+/).find((e=>h(e)||S(e)))}(e);if(h(n))return;O("before:highlightElement",{el:e,language:n}),t=e;const s=t.textContent,o=n?d(s,{language:n,ignoreIllegals:!0}):m(s);O("after:highlightElement",{el:e,result:o,text:s}),e.innerHTML=o.value,function(e,t,n){const s=t?r[t]:n;e.classList.add("hljs"),s&&e.classList.add(s)}(e,n,o.language),e.result={language:o.language,re:o.relevance,relavance:o.relevance},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.relevance,relavance:o.second_best.relevance})}const E=()=>{if(E.called)return;E.called=!0,Q("10.6.0","initHighlighting() is deprecated. Use highlightAll() instead.");document.querySelectorAll("pre code").forEach(b)};let w=!1;function x(){if("loading"===document.readyState)return void(w=!0);document.querySelectorAll("pre code").forEach(b)}function S(e){return e=(e||"").toLowerCase(),t[e]||t[r[e]]}function _(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{r[e.toLowerCase()]=t}))}function A(e){const t=S(e);return t&&!t.disableAutodetect}function O(e,t){const n=e;o.forEach((function(e){e[n]&&e[n](t)}))}"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(function(){w&&x()}),!1),Object.assign(e,{highlight:d,highlightAuto:m,highlightAll:x,fixMarkup:function(e){return Q("10.2.0","fixMarkup will be removed entirely in v11.0"),Q("10.2.0","Please see https://github.com/highlightjs/highlight.js/issues/2534"),t=e,p.tabReplace||p.useBR?t.replace(a,(e=>"\n"===e?p.useBR?"
":e:p.tabReplace?e.replace(/\t/g,p.tabReplace):e)):t;var t},highlightElement:b,highlightBlock:function(e){return Q("10.7.0","highlightBlock will be removed entirely in v12.0"),Q("10.7.0","Please use highlightElement now."),b(e)},configure:function(e){e.useBR&&(Q("10.3.0","'useBR' will be removed entirely in v11.0"),Q("10.3.0","Please see https://github.com/highlightjs/highlight.js/issues/2559")),p=te(p,e)},initHighlighting:E,initHighlightingOnLoad:function(){Q("10.6.0","initHighlightingOnLoad() is deprecated. Use highlightAll() instead."),w=!0},registerLanguage:function(n,r){let s=null;try{s=r(e)}catch(o){if(X("Language definition for '{}' could not be registered.".replace("{}",n)),!i)throw o;X(o),s=l}s.name||(s.name=n),t[n]=s,s.rawDefinition=r.bind(null,e),s.aliases&&_(s.aliases,{languageName:n})},unregisterLanguage:function(e){delete t[e];for(const t of Object.keys(r))r[t]===e&&delete r[t]},listLanguages:function(){return Object.keys(t)},getLanguage:S,registerAliases:_,requireLanguage:function(e){Q("10.4.0","requireLanguage will be removed entirely in v11."),Q("10.4.0","Please see https://github.com/highlightjs/highlight.js/pull/2844");const t=S(e);if(t)return t;throw new Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:A,inherit:te,addPlugin:function(e){!function(e){e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{e["before:highlightBlock"](Object.assign({block:t.el},t))}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{e["after:highlightBlock"](Object.assign({block:t.el},t))})}(e),o.push(e)},vuePlugin:J(e).VuePlugin}),e.debugMode=function(){i=!1},e.safeMode=function(){i=!0},e.versionString="10.7.3";for(const s in M)"object"==typeof M[s]&&n(M[s]);return Object.assign(e,M),e.addPlugin(g),e.addPlugin(W),e.addPlugin(v),e}({});e.exports=re},35344:e=>{function t(...e){return e.map((e=>{return(t=e)?"string"==typeof t?t:t.source:null;var t})).join("")}e.exports=function(e){const n={},r={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{begin:t(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},r]});const s={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},o={begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},i={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,n,s]};s.contains.push(i);const a={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,n]},c=e.SHEBANG({binary:`(${["fish","bash","zsh","sh","csh","ksh","tcsh","dash","scsh"].join("|")})`,relevance:10}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z._-]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp"},contains:[c,e.SHEBANG(),l,a,e.HASH_COMMENT_MODE,o,i,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},n]}}},73402:e=>{function t(...e){return e.map((e=>{return(t=e)?"string"==typeof t?t:t.source:null;var t})).join("")}e.exports=function(e){const n="HTTP/(2|1\\.[01])",r={className:"attribute",begin:t("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]}},s=[r,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+n+" \\d{3})",end:/$/,contains:[{className:"meta",begin:n},{className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:s}},{begin:"(?=^[A-Z]+ (.*?) "+n+"$)",end:/$/,contains:[{className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:n},{className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:s}},e.inherit(r,{relevance:0})]}}},95089:e=>{const t="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],r=["true","false","null","undefined","NaN","Infinity"],s=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]);function o(e){return i("(?=",e,")")}function i(...e){return e.map((e=>{return(t=e)?"string"==typeof t?t:t.source:null;var t})).join("")}e.exports=function(e){const a=t,c="<>",l=">",u={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,t)=>{const n=e[0].length+e.index,r=e.input[n];"<"!==r?">"===r&&(((e,{after:t})=>{const n=""+e[0].slice(1);return-1!==e.input.indexOf(n,t)})(e,{after:n})||t.ignoreMatch()):t.ignoreMatch()}},p={$pattern:t,keyword:n,literal:r,built_in:s},h="[0-9](_?[0-9])*",d=`\\.(${h})`,f="0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*",m={className:"number",variants:[{begin:`(\\b(${f})((${d})|\\.)?|(${d}))[eE][+-]?(${h})\\b`},{begin:`\\b(${f})\\b((${d})\\b|\\.)?|(${d})\\b`},{begin:"\\b(0|[1-9](_?[0-9])*)n\\b"},{begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*n?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*n?\\b"},{begin:"\\b0[0-7]+n?\\b"}],relevance:0},g={className:"subst",begin:"\\$\\{",end:"\\}",keywords:p,contains:[]},y={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,g],subLanguage:"xml"}},v={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,g],subLanguage:"css"}},b={className:"string",begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE,g]},E={className:"comment",variants:[e.COMMENT(/\/\*\*(?!\/)/,"\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+",contains:[{className:"type",begin:"\\{",end:"\\}",relevance:0},{className:"variable",begin:a+"(?=\\s*(-)|$)",endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]}),e.C_BLOCK_COMMENT_MODE,e.C_LINE_COMMENT_MODE]},w=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,y,v,b,m,e.REGEXP_MODE];g.contains=w.concat({begin:/\{/,end:/\}/,keywords:p,contains:["self"].concat(w)});const x=[].concat(E,g.contains),S=x.concat([{begin:/\(/,end:/\)/,keywords:p,contains:["self"].concat(x)}]),_={className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:p,contains:S};return{name:"Javascript",aliases:["js","jsx","mjs","cjs"],keywords:p,exports:{PARAMS_CONTAINS:S},illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:"shebang",binary:"node",relevance:5}),{label:"use_strict",className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,y,v,b,E,m,{begin:i(/[{,\n]\s*/,o(i(/(((\/\/.*$)|(\/\*(\*[^/]|[^*])*\*\/))\s*)*/,a+"\\s*:"))),relevance:0,contains:[{className:"attr",begin:a+o("\\s*:"),relevance:0}]},{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[E,e.REGEXP_MODE,{className:"function",begin:"(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+e.UNDERSCORE_IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:p,contains:S}]}]},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:c,end:l},{begin:u.begin,"on:begin":u.isTrulyOpeningTag,end:u.end}],subLanguage:"xml",contains:[{begin:u.begin,end:u.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:p,contains:["self",e.inherit(e.TITLE_MODE,{begin:a}),_],illegal:/%/},{beginKeywords:"while if switch catch for"},{className:"function",begin:e.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,contains:[_,e.inherit(e.TITLE_MODE,{begin:a})]},{variants:[{begin:"\\."+a},{begin:"\\$"+a}],relevance:0},{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{beginKeywords:"extends"},e.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/,end:/[{;]/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:a}),"self",_]},{begin:"(get|set)\\s+(?="+a+"\\()",end:/\{/,keywords:"get set",contains:[e.inherit(e.TITLE_MODE,{begin:a}),{begin:/\(\)/},_]},{begin:/\$[(.]/}]}}},65772:e=>{e.exports=function(e){const t={literal:"true false null"},n=[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],r=[e.QUOTE_STRING_MODE,e.C_NUMBER_MODE],s={end:",",endsWithParent:!0,excludeEnd:!0,contains:r,keywords:t},o={begin:/\{/,end:/\}/,contains:[{className:"attr",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE],illegal:"\\n"},e.inherit(s,{begin:/:/})].concat(n),illegal:"\\S"},i={begin:"\\[",end:"\\]",contains:[e.inherit(s)],illegal:"\\S"};return r.push(o,i),n.forEach((function(e){r.push(e)})),{name:"JSON",contains:r,keywords:t,illegal:"\\S"}}},26571:e=>{e.exports=function(e){const t={$pattern:/-?[A-z\.\-]+\b/,keyword:"if else foreach return do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch hidden static parameter",built_in:"ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write"},n={begin:"`[\\s\\S]",relevance:0},r={className:"variable",variants:[{begin:/\$\B/},{className:"keyword",begin:/\$this/},{begin:/\$[\w\d][\w\d_:]*/}]},s={className:"string",variants:[{begin:/"/,end:/"/},{begin:/@"/,end:/^"@/}],contains:[n,r,{className:"variable",begin:/\$[A-z]/,end:/[^A-z]/}]},o={className:"string",variants:[{begin:/'/,end:/'/},{begin:/@'/,end:/^'@/}]},i=e.inherit(e.COMMENT(null,null),{variants:[{begin:/#/,end:/$/},{begin:/<#/,end:/#>/}],contains:[{className:"doctag",variants:[{begin:/\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/},{begin:/\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/}]}]}),a={className:"built_in",variants:[{begin:"(".concat("Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where",")+(-)[\\w\\d]+")}]},c={className:"class",beginKeywords:"class enum",end:/\s*[{]/,excludeEnd:!0,relevance:0,contains:[e.TITLE_MODE]},l={className:"function",begin:/function\s+/,end:/\s*\{|$/,excludeEnd:!0,returnBegin:!0,relevance:0,contains:[{begin:"function",relevance:0,className:"keyword"},{className:"title",begin:/\w[\w\d]*((-)[\w\d]+)*/,relevance:0},{begin:/\(/,end:/\)/,className:"params",relevance:0,contains:[r]}]},u={begin:/using\s/,end:/$/,returnBegin:!0,contains:[s,o,{className:"keyword",begin:/(using|assembly|command|module|namespace|type)/}]},p={variants:[{className:"operator",begin:"(".concat("-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|-split|-wildcard|-xor",")\\b")},{className:"literal",begin:/(-)[\w\d]+/,relevance:0}]},h={className:"function",begin:/\[.*\]\s*[\w]+[ ]??\(/,end:/$/,returnBegin:!0,relevance:0,contains:[{className:"keyword",begin:"(".concat(t.keyword.toString().replace(/\s/g,"|"),")\\b"),endsParent:!0,relevance:0},e.inherit(e.TITLE_MODE,{endsParent:!0})]},d=[h,i,n,e.NUMBER_MODE,s,o,a,r,{className:"literal",begin:/\$(null|true|false)\b/},{className:"selector-tag",begin:/@\B/,relevance:0}],f={begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[].concat("self",d,{begin:"("+["string","char","byte","int","long","bool","decimal","single","double","DateTime","xml","array","hashtable","void"].join("|")+")",className:"built_in",relevance:0},{className:"type",begin:/[\.\w\d]+/,relevance:0})};return h.contains.unshift(f),{name:"PowerShell",aliases:["ps","ps1"],case_insensitive:!0,keywords:t,contains:d.concat(c,l,u,p,f)}}},17285:e=>{function t(e){return e?"string"==typeof e?e:e.source:null}function n(e){return r("(?=",e,")")}function r(...e){return e.map((e=>t(e))).join("")}function s(...e){return"("+e.map((e=>t(e))).join("|")+")"}e.exports=function(e){const t=r(/[A-Z_]/,r("(",/[A-Z0-9_.-]*:/,")?"),/[A-Z0-9_.-]*/),o={className:"symbol",begin:/&[a-z]+;|[0-9]+;|[a-f0-9]+;/},i={begin:/\s/,contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},a=e.inherit(i,{begin:/\(/,end:/\)/}),c=e.inherit(e.APOS_STRING_MODE,{className:"meta-string"}),l=e.inherit(e.QUOTE_STRING_MODE,{className:"meta-string"}),u={endsWithParent:!0,illegal:/,relevance:0,contains:[{className:"attr",begin:/[A-Za-z0-9._:-]+/,relevance:0},{begin:/=\s*/,relevance:0,contains:[{className:"string",endsParent:!0,variants:[{begin:/"/,end:/"/,contains:[o]},{begin:/'/,end:/'/,contains:[o]},{begin:/[^\s"'=<>`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[i,l,c,a,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[i,a,l,c]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},o,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:/