@goodfellow-cms/broker 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/site/assets/{content-repository-setup-HEL-uoaX.js → content-repository-setup-0zqQHkZ9.js} +2 -2
- package/site/assets/dist-86wrqcsN.js +6 -0
- package/site/assets/dist-C2zb_90U.js +2 -0
- package/site/assets/dist-DJGm2ktT.js +21 -0
- package/site/assets/index-C1mWwm_b.js +234 -0
- package/site/assets/{index-BQoQNxGe.css → index-DrAt6GVO.css} +1 -1
- package/site/assets/preload-helper-9CpHFPb-.js +1 -0
- package/site/assets/{setup-host-DQm73dc_.js → setup-host-BAQmd0y1.js} +1 -1
- package/site/assets/{store-BtVaZcVF.js → store-BJ3bMnko.js} +1 -1
- package/site/files.json +9 -9
- package/site/index.html +4 -4
- package/site/assets/dist-DAzQ31j6.js +0 -5
- package/site/assets/dist-Dkr_h4iS.js +0 -2
- package/site/assets/dist-Dob4V5zY.js +0 -6
- package/site/assets/index-BL-VYiot.js +0 -234
- package/site/assets/preload-helper-khBccGFq.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--bg:var(--lightningcss-light,#fff)var(--lightningcss-dark,#14161a);--fg:var(--lightningcss-light,#1b1f24)var(--lightningcss-dark,#e8eaed);--muted:var(--lightningcss-light,#5b6470)var(--lightningcss-dark,#a3aab4);--line:var(--lightningcss-light,#d9dde3)var(--lightningcss-dark,#343a42);--accent:var(--lightningcss-light,#1e3a8a)var(--lightningcss-dark,#93b4ff);--accent-fg:var(--lightningcss-light,#fff)var(--lightningcss-dark,#0b1530);--error:var(--lightningcss-light,#a3221b)var(--lightningcss-dark,#ff9a92);font-family:system-ui,sans-serif}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}html,body{background:var(--bg);height:100%;color:var(--fg);margin:0}#broker{flex-direction:column;height:100%;display:flex}.broker-note,.broker-sign-in{max-width:32rem;margin:4rem auto;padding:0 1rem;line-height:1.5}.broker-sign-in{flex-direction:column;gap:.75rem;display:flex}.broker-sign-in h1{margin:0;font-size:1.5rem}.broker-sign-in h2{margin:1rem 0 0;font-size:1rem}input[type=password]{border:1px solid var(--line);background:var(--bg);width:100%;color:var(--fg);font:inherit;border-radius:.375rem;padding:.5rem}button{border:1px solid var(--line);background:var(--bg);color:var(--fg);font:inherit;cursor:pointer;border-radius:.375rem;padding:.4rem .9rem}.broker-primary,button[type=submit]{background:var(--accent);border-color:var(--accent);color:var(--accent-fg)}a{color:var(--accent)}.broker-error{color:var(--error);min-height:1lh;margin:0}.broker-check{align-items:center;gap:.25rem;display:flex}.broker-bar{border-bottom:1px solid var(--line);color:var(--muted);justify-content:flex-end;align-items:center;gap:.75rem;padding:.25rem .75rem;font-size:.875rem;display:flex}.broker-bar button{padding:.15rem .6rem}.broker-frame{border:0;flex:1;width:100%}.broker-dialog{border:1px solid var(--line);background:var(--bg);max-width:34rem;color:var(--fg);border-radius:.5rem;line-height:1.5}.broker-dialog::backdrop{background:#0006}.broker-dialog label{margin-top:.5rem;display:block}.broker-actions{justify-content:flex-end;gap:.5rem;margin-top:1rem;display:flex}
|
|
1
|
+
:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;--bg:var(--lightningcss-light,#fff)var(--lightningcss-dark,#14161a);--fg:var(--lightningcss-light,#1b1f24)var(--lightningcss-dark,#e8eaed);--muted:var(--lightningcss-light,#5b6470)var(--lightningcss-dark,#a3aab4);--line:var(--lightningcss-light,#d9dde3)var(--lightningcss-dark,#343a42);--accent:var(--lightningcss-light,#1e3a8a)var(--lightningcss-dark,#93b4ff);--accent-fg:var(--lightningcss-light,#fff)var(--lightningcss-dark,#0b1530);--error:var(--lightningcss-light,#a3221b)var(--lightningcss-dark,#ff9a92);font-family:system-ui,sans-serif}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}}*{box-sizing:border-box}html,body{background:var(--bg);height:100%;color:var(--fg);margin:0}#broker{flex-direction:column;height:100%;display:flex}.broker-note,.broker-sign-in{max-width:32rem;margin:4rem auto;padding:0 1rem;line-height:1.5}.broker-sign-in{flex-direction:column;gap:.75rem;display:flex}.broker-sign-in h1{margin:0;font-size:1.5rem}.broker-sign-in h2{margin:1rem 0 0;font-size:1rem}input[type=password]{border:1px solid var(--line);background:var(--bg);width:100%;color:var(--fg);font:inherit;border-radius:.375rem;padding:.5rem}button{border:1px solid var(--line);background:var(--bg);color:var(--fg);font:inherit;cursor:pointer;border-radius:.375rem;padding:.4rem .9rem}.broker-primary,button[type=submit]{background:var(--accent);border-color:var(--accent);color:var(--accent-fg)}a{color:var(--accent)}.broker-error{color:var(--error);min-height:1lh;margin:0}.broker-check{align-items:center;gap:.25rem;display:flex}.broker-bar{border-bottom:1px solid var(--line);color:var(--muted);justify-content:flex-end;align-items:center;gap:.75rem;padding:.25rem .75rem;font-size:.875rem;display:flex}.broker-origin{overflow-wrap:anywhere;margin-inline-end:auto}.broker-bar button{padding:.15rem .6rem}.broker-frame{border:0;flex:1;width:100%}.broker-dialog{border:1px solid var(--line);background:var(--bg);max-width:34rem;color:var(--fg);border-radius:.5rem;line-height:1.5}.broker-dialog::backdrop{background:#0006}.broker-dialog label{margin-top:.5rem;display:block}.broker-actions{justify-content:flex-end;gap:.5rem;margin-top:1rem;display:flex}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=/^[A-Za-z0-9-]+\/[A-Za-z0-9._-]+$/,t=/^[A-Za-z0-9_-]+$/,n=class extends Error{problem;link;name=`CommentsError`;constructor(e,t,n){super(t),this.problem=e,this.link=n}},r=`https://github.com/apps/giscus`,i=(function(){let e=typeof document<`u`&&document.createElement(`link`).relList;return e&&e.supports&&e.supports(`modulepreload`)?`modulepreload`:`preload`})(),a=function(e,t){return new URL(e,t).href},o={},s=function(e){return e.pathname.endsWith(`.css`)},c=function(e,t,n){if(t in e)return e[t];let r=n();if(!r){e[t]=void 0;return}let i=r.then(()=>{e[t]=void 0},n=>{throw e[t]=void 0,n});return e[t]=i,i},l=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e,l=document.querySelector(`meta[property=csp-nonce]`),u=l?.nonce||l?.getAttribute(`nonce`);function d(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function f(e){return import.meta.resolve?new URL(import.meta.resolve(e)):new URL(e,import.meta.url)}r=d(t.map(t=>{t=a(t,n);let r=f(t),l=s(r);return c(o,r.href,()=>{if(e===void 0){e={all:new Set,styles:new Set};let t=document.getElementsByTagName(`link`);for(let n=t.length-1;n>=0;n--){let r=t[n];e.all.add(r.href),r.rel===`stylesheet`&&e.styles.add(r.href)}}if((l?e.styles:e.all).has(r.href))return;let t=document.createElement(`link`);if(t.rel=l?`stylesheet`:i,l||(t.as=`script`),t.crossOrigin=``,t.href=r.href,u&&t.setAttribute(`nonce`,u),document.head.appendChild(t),l)return new Promise((e,n)=>{t.addEventListener(`load`,e),t.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${r}`)))})})}).filter(e=>e!==void 0))}function l(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&l(e.reason);return e().catch(l)})};export{r as a,n as i,t as n,e as r,l as t};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e}from"./store-
|
|
1
|
+
import{a as e}from"./store-BJ3bMnko.js";function t(e){let t=/^[\^~=v]*(\d+)\.(\d+)\.(\d+)$/.exec(e.trim());return t?[Number(t[1]),Number(t[2]),Number(t[3])]:void 0}function n(e,t){return e[0]-t[0]||e[1]-t[1]||e[2]-t[2]}function r(e,r){let i=t(e),a=t(r);return i&&a?n(i,a):0}function i(e){return t(e)?.join(`.`)}function a(e){try{let{dependencies:t={},devDependencies:n={}}=JSON.parse(e),r=t[`@goodfellow-cms/react`]??n[`@goodfellow-cms/react`];return r?i(r):void 0}catch{return}}var o=`goodfellow-update `;function s(e){let t=e.split(`
|
|
2
2
|
`);for(let e=t.length-1;e>=0;e--){let n=t[e]??``,r=n.indexOf(o);if(r!==-1)try{let e=JSON.parse(n.slice(r+18).trim());if([`up-to-date`,`updated`,`failed`].includes(e.state)&&typeof e.from==`string`)return e}catch{}}}var c=`GOODFELLOW_NIGHTLY`,l=[`changed`,`always`,`off`];function u(e){let t=e?.trim().toLowerCase();return l.includes(t)?t:`changed`}var d=class extends Error{problem;name=`UpdatesError`;constructor(e,t){super(t),this.problem=e}},f=/^[a-z0-9]{8,40}$/,p=`goodfellow-task-`,m=`goodfellow-task-result.json`,h=`plugin-task.yml`,g=`plugin-task`,_=`goodfellow-plugin-task`;function v(e){return f.test(e)}function y(e){let{id:t,plugin:n,task:r,input:i,key:a}=e;if(![t,n,r,i,a].every(e=>typeof e==`string`))return`That isn't a task's request.`;if(!v(e.id))return`The request's id isn't one the admin panel makes.`;if(!/^[a-z0-9][a-z0-9._-]*(--[a-z0-9][a-z0-9._-]*)?$/.test(e.plugin))return`That isn't a plugin's id.`;if(!/^[a-z0-9][a-z0-9-]*$/.test(e.task))return`That isn't a task's id.`;if(e.input.length>32e3)return`The task's input is too long.`;try{JSON.parse(e.input);let t=JSON.parse(e.key);if(t.kty!==`EC`||t.crv!==`P-256`||t.d!==void 0)return`The answer's key isn't a public key.`}catch{return`The task's input or key isn't JSON.`}}var b=class extends Error{problem;name=`PluginTaskError`;constructor(e,t){super(t),this.problem=e}},x=3e5,S=4e3,C=`goodfellow-draft-`,w=/^[a-z0-9][a-z0-9-]{0,39}$/;function T(e){return w.test(e)}var E=class extends Error{name=`DraftError`;problem;constructor(e,t){super(t),this.problem=e}};function D(e){if(!T(e))throw new E(`not-found`,`"${e}" isn't a draft's name.`);return`${C}${e}`}function O(t,n){async function r(e){try{await n.closeReview(e)}catch{}}function i(i,a){let o=n.branchStore(a);async function s(){let e=await n.mergeBase(a);return o.changedPaths(e,await o.revision())}async function c(){let e=[];for(let t of await s())if(t.startsWith(`public/media/`)){let n=await o.readBytes(t);e.push(n?{path:t,bytes:n}:{path:t,delete:!0})}else{let n=await o.read(t);e.push(n===void 0?{path:t,delete:!0}:{path:t,content:n})}return e}return{name:i,store:o,changes:c,paths:s,async publish(i){let o=await n.mergeBase(a),s=await c(),l=s.length>0?await e(t,s,{message:i,expectedRevision:o}):{revision:await t.revision()};return await r(a),await n.deleteBranch(a),l},async submitForReview({title:e,description:t=``,reviewers:r}){return n.openReview({branch:a,title:e,description:t,...r?.length&&{reviewers:r}})},async discard(){await r(a),await n.deleteBranch(a)}}}return{async create(e,r){let a=D(e);return await n.createBranch(a,r?.from??await t.revision()),i(e,a)},async open(e){let t=D(e);return await n.mergeBase(t),i(e,t)},async list(){return(await n.listBranches(C)).map(e=>e.slice(17)).filter(T).sort().reverse()},async reviews(){return(await n.listReviews(C)).map(e=>({name:e.branch.slice(17),url:e.url,title:e.title})).filter(e=>T(e.name)).sort((e,t)=>t.name.localeCompare(e.name))}}}var k=class extends Error{problem;name=`EditorsError`;constructor(e,t){super(t),this.problem=e}},A=3,j=class extends Error{name=`RateLimitError`;status;resetsAt;constructor(e,t,n){super(`${n} is limiting how many requests this sign-in can make${t?` until ${t.toISOString()}`:` for now`}.`),this.status=e,t&&(this.resetsAt=t)}};function M(e,t=Date.now()){let n=e.get(`retry-after`);if(n){let e=Number(n);if(Number.isFinite(e))return Math.max(0,e*1e3);let r=Date.parse(n);if(Number.isFinite(r))return Math.max(0,r-t)}let r=e.get(`ratelimit-reset`)??e.get(`x-ratelimit-reset`);if(r&&/^\d+$/.test(r))return Math.max(0,Number(r)*1e3-t)}function N(e){return e.status===429||e.status===403&&(e.headers.has(`retry-after`)||e.headers.get(`x-ratelimit-remaining`)===`0`)}function P(e,t){let n=t.sleep??(e=>new Promise(t=>globalThis.setTimeout(t,e))),r=t.now??Date.now,i=e=>typeof e?.getReader==`function`;return(async(a,o)=>{let s=!i(o?.body)&&!i(a?.body);for(let i=0;;i++){let c=await e(a,o);if(!s||!N(c))return c;let l=M(c.headers,r()),u=Math.max(l??5e3*2**i,1e3);if(i>=A||u>6e4)throw new j(c.status,l===void 0?void 0:new Date(r()+l),t.host);await c.body?.cancel().catch(()=>{}),await n(u)}})}var F=class extends Error{problem;link;name=`SetupError`;constructor(e,t,n){super(t),this.problem=e,this.link=n}};export{r as _,O as a,a as b,_ as c,m as d,x as f,d as g,c as h,E as i,g as l,y as m,P as n,b as o,h as p,k as r,p as s,F as t,S as u,s as v,u as y};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=`content`,t=`content/pages`,n=`content/site.json`,r=`content/menus.json`,i=`content/permissions.json`,a=`public/media`,o=`content/collections`,s=`blocks/installed`,c=`plugins/installed`,l=`plugins/installed/installed.json`,u=`components`,d=`hooks`,f=`content-repository`,p=`_collection.json`,m=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,h=class extends Error{name=`InvalidPathError`};function g(e){if(!e.startsWith(`/`))throw new h(`Page addresses must start with "/" (got "${e}").`);let t=e.split(`/`).filter(e=>e!==``);for(let e of t)if(!m.test(e))throw new h(`"${e}" can't be part of a page address. Use lowercase letters, numbers and hyphens only.`);return t}function _(e){return`/${g(e).join(`/`)}`}function v(e){let n=`${t}/`;if(!e.startsWith(n)||!e.endsWith(`.json`))throw new h(`${e} is not a page file. Pages are .json files in ${t}/.`);let r=e.slice(n.length,-5).split(`/`);return r.at(-1)===`index`&&r.pop(),_(`/${r.join(`/`)}`)}var y=`{slug}`;function b(e){if(!e.startsWith(`/`))return`must start with "/".`;let t=e.split(`/`).filter(e=>e!==``);if(t.filter(e=>e===`{slug}`).length!==1)return`must contain ${y} exactly once, such as /videos/${y}.`;let n=t.find(e=>e!==`{slug}`&&!m.test(e));if(n!==void 0)return`can't contain "${n}". Use lowercase letters, numbers and hyphens only.`}var x=class extends Error{name=`ConflictError`;constructor(e=`The site changed since it was loaded.`){super(e)}},S=[e,a,s,u,`lib`,d,c];function C(e){return e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`)||e.split(`/`).some(e=>e===``||e===`.`||e===`..`)?!1:S.some(t=>e.startsWith(`${t}/`))}async function w(e,t,n){let r=n.expectedRevision,i=new Set(t.map(e=>e.path));for(let a=0;;a++)try{return await e.write(t,{...n,expectedRevision:r})}catch(t){if(!(t instanceof x)||!e.changedPaths||a===2)throw t;let o=await e.revision();if(o===r
|
|
1
|
+
var e=`content`,t=`content/pages`,n=`content/site.json`,r=`content/menus.json`,i=`content/permissions.json`,a=`public/media`,o=`content/collections`,s=`blocks/installed`,c=`plugins/installed`,l=`plugins/installed/installed.json`,u=`components`,d=`hooks`,f=`content-repository`,p=`_collection.json`,m=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,h=class extends Error{name=`InvalidPathError`};function g(e){if(!e.startsWith(`/`))throw new h(`Page addresses must start with "/" (got "${e}").`);let t=e.split(`/`).filter(e=>e!==``);for(let e of t)if(!m.test(e))throw new h(`"${e}" can't be part of a page address. Use lowercase letters, numbers and hyphens only.`);return t}function _(e){return`/${g(e).join(`/`)}`}function v(e){let n=`${t}/`;if(!e.startsWith(n)||!e.endsWith(`.json`))throw new h(`${e} is not a page file. Pages are .json files in ${t}/.`);let r=e.slice(n.length,-5).split(`/`);return r.at(-1)===`index`&&r.pop(),_(`/${r.join(`/`)}`)}var y=`{slug}`;function b(e){if(!e.startsWith(`/`))return`must start with "/".`;let t=e.split(`/`).filter(e=>e!==``);if(t.filter(e=>e===`{slug}`).length!==1)return`must contain ${y} exactly once, such as /videos/${y}.`;let n=t.find(e=>e!==`{slug}`&&!m.test(e));if(n!==void 0)return`can't contain "${n}". Use lowercase letters, numbers and hyphens only.`}var x=class extends Error{name=`ConflictError`;constructor(e=`The site changed since it was loaded.`){super(e)}},S=[e,a,s,u,`lib`,d,c];function C(e){return e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`)||e.split(`/`).some(e=>e===``||e===`.`||e===`..`)?!1:S.some(t=>e.startsWith(`${t}/`))}async function w(e,t,n){let r=n.expectedRevision,i=new Set(t.map(e=>e.path));for(let a=0;;a++)try{return await e.write(t,{...n,expectedRevision:r})}catch(t){if(!(t instanceof x)||!e.changedPaths||a===2)throw t;let o=await e.revision();if(o===r)throw t;let s=await e.changedPaths(n.expectedRevision,o).catch(()=>void 0);if(!s||s.some(e=>i.has(e)))throw t;r=o}}var T=[e,a];function E(e){return C(e)&&T.some(t=>e.startsWith(`${t}/`))}var D=class extends Error{name=`CodeChangeError`;constructor(e){super(`${e} is part of the site's code, which is kept in a repository of its own, not the content repository.`)}};function O(e){let t=e.find(e=>!E(e.path));if(t)throw new D(t.path)}export{w as a,f as c,i as d,n as f,E as i,l,v as m,S as n,o,b as p,O as r,p as s,x as t,r as u};
|
package/site/files.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": [
|
|
3
3
|
"_headers",
|
|
4
|
-
"assets/content-repository-setup-
|
|
4
|
+
"assets/content-repository-setup-0zqQHkZ9.js",
|
|
5
5
|
"assets/deploy-keys-DAj2oX-N-DRd_HmOG.js",
|
|
6
|
-
"assets/dist-
|
|
7
|
-
"assets/dist-
|
|
8
|
-
"assets/dist-
|
|
6
|
+
"assets/dist-86wrqcsN.js",
|
|
7
|
+
"assets/dist-C2zb_90U.js",
|
|
8
|
+
"assets/dist-DJGm2ktT.js",
|
|
9
9
|
"assets/git-eGyMXUIu.js",
|
|
10
|
-
"assets/index-
|
|
11
|
-
"assets/index-
|
|
12
|
-
"assets/preload-helper-
|
|
10
|
+
"assets/index-C1mWwm_b.js",
|
|
11
|
+
"assets/index-DrAt6GVO.css",
|
|
12
|
+
"assets/preload-helper-9CpHFPb-.js",
|
|
13
13
|
"assets/scheduled-builds-BPfDaBYt.js",
|
|
14
|
-
"assets/setup-host-
|
|
15
|
-
"assets/store-
|
|
14
|
+
"assets/setup-host-BAQmd0y1.js",
|
|
15
|
+
"assets/store-BJ3bMnko.js",
|
|
16
16
|
"broker.example.json",
|
|
17
17
|
"index.html",
|
|
18
18
|
"vercel.json"
|
package/site/index.html
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
/>
|
|
10
10
|
<meta name="referrer" content="no-referrer" />
|
|
11
11
|
<title>Sign in</title>
|
|
12
|
-
<script type="module" crossorigin src="./assets/index-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="./assets/store-
|
|
14
|
-
<link rel="modulepreload" crossorigin href="./assets/preload-helper-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
12
|
+
<script type="module" crossorigin src="./assets/index-C1mWwm_b.js"></script>
|
|
13
|
+
<link rel="modulepreload" crossorigin href="./assets/store-BJ3bMnko.js">
|
|
14
|
+
<link rel="modulepreload" crossorigin href="./assets/preload-helper-9CpHFPb-.js">
|
|
15
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DrAt6GVO.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="broker"></div>
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./deploy-keys-DAj2oX-N-DRd_HmOG.js","./git-eGyMXUIu.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{r as e,t}from"./store-BtVaZcVF.js";import{_ as n,a as r,b as i,c as a,d as o,g as s,h as c,i as l,m as u,n as d,o as f,p,r as m,s as h,t as g,y as _}from"./setup-host-DQm73dc_.js";import{i as v,n as y,t as b}from"./content-repository-setup-HEL-uoaX.js";import{a as x,i as S,n as C,o as w,r as T,s as ee,t as E}from"./git-eGyMXUIu.js";import{t as te}from"./preload-helper-khBccGFq.js";async function D({apiUrl:e,token:t,fetch:n},r,i={}){let a=async a=>n(`${e}${r}`,{method:i.method??`GET`,headers:{accept:i.accept??`application/vnd.github+json`,authorization:`Bearer ${typeof t==`string`?t:await t({refresh:a})}`,"x-github-api-version":`2022-11-28`,...i.body!==void 0&&{"content-type":`application/json`}},body:i.body===void 0?void 0:JSON.stringify(i.body),cache:`no-store`}),o=await a(!1);if(o.status===401&&typeof t!=`string`&&(o=await a(!0)),o.status===401)throw new C(`invalid`,`GitHub didn't accept the sign-in. It may have expired.`);if(!o.ok&&!i.allow?.includes(o.status)){let e=await o.json().catch(()=>({}));throw new E(o.status,`GitHub answered ${o.status}: ${e.message??o.statusText}`)}return o}async function O(e,t,n){return await(await D(e,t,n)).json()}function k(e){return e.split(`/`).map(e=>encodeURIComponent(e)).join(`/`)}var ne=/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i,A=`invitation:`;function re(e){return e?.admin?`owner`:e?.maintain||e?.push?`editor`:`viewer`}function ie(e){return e===`admin`?`owner`:e===`write`||e===`maintain`?`editor`:`viewer`}function j(e){return e instanceof E&&(e.status===403||e.status===404)}function ae(e,t,n,r){let i=`/repos/${n}`;function a(){let e=t();if(!e)throw new m(`not-allowed`,`Changing editors on GitHub needs an owner token.`);return e}async function o(e){try{await e(a())}catch(e){throw j(e)?new m(`not-allowed`,`This token can't change the site's editors.`):e}}async function s(e){let t=[];for(let n=1;n<=10;n++){let r=await O(e,`${i}/collaborators?per_page=100&page=${n}`);if(t.push(...r),r.length<100)break}return t}return{invitesByEmail:!1,async list(){let n=t()??e,a=await s(n),o;try{o=await O(n,`${i}/invitations?per_page=100`)}catch(e){if(!j(e))throw e}let c=[...a.map(e=>({id:e.login,login:e.login,avatarUrl:e.avatar_url,role:re(e.permissions),...e.login.toLowerCase()===r.toLowerCase()&&{self:!0}})),...(o??[]).flatMap(e=>e.invitee?[{id:`${A}${e.id}`,login:e.invitee.login,avatarUrl:e.invitee.avatar_url,role:ie(e.permissions),invited:!0}]:[])],l=c.some(e=>e.self&&e.role===`owner`);return{editors:c,manage:o?`yes`:l?`token`:`no`,editorsCanPublish:!0}},async invite(e,t){let n=e.trim().replace(/^@/,``);if(!ne.test(n))throw new m(`invalid`,`That isn't a GitHub username.`);let r=a();try{await D(r,`${i}/collaborators/${encodeURIComponent(n)}`,{method:`PUT`,body:{permission:t===`owner`?`admin`:`push`}})}catch(e){throw e instanceof E&&e.status===404&&(await D(r,`/users/${encodeURIComponent(n)}`,{allow:[404]})).status===404?new m(`not-found`,`There's no GitHub account named ${n}.`):j(e)?new m(`not-allowed`,`This token can't change the site's editors.`):e instanceof E&&e.status===422?new m(`invalid`,`GitHub didn't accept the invitation: ${e.message}`):e}},async setRole(e,t){await o(async n=>{e.id.startsWith(A)?await D(n,`${i}/invitations/${e.id.slice(11)}`,{method:`PATCH`,body:{permissions:t===`owner`?`admin`:`write`}}):await D(n,`${i}/collaborators/${encodeURIComponent(e.id)}`,{method:`PUT`,body:{permission:t===`owner`?`admin`:`push`}})})},async remove(e){await o(t=>D(t,e.id.startsWith(A)?`${i}/invitations/${e.id.slice(11)}`:`${i}/collaborators/${encodeURIComponent(e.id)}`,{method:`DELETE`}))}}}function M(e,t,n,r){let i,a,o,s;return{access:{tokenLink:n,get active(){return i!==void 0},get problem(){return s},...r&&{async startRedirect(e){s=void 0,await r(e)}},async applyToken(n){let r={...e,token:n.trim()};try{if(!(await O(r,`/repos/${t}`)).permissions?.admin)throw new m(`not-allowed`,`This token's account isn't an owner of the site.`);await O(r,`/repos/${t}/invitations?per_page=1`)}catch(e){throw e instanceof m?e:e instanceof C||j(e)?new m(`not-allowed`,`This token can't change the site's editors.`):e}i=r,a=r,s=void 0},forget(){i=void 0,a=void 0,o?.(),o=void 0}},api:()=>i,codeApi:()=>a,useSignIn(t,n,r){i={...e,token:t},a=r?{...e,token:r}:void 0,o=n,s=void 0},failed(e){s=e}}}var oe=[`185.199.108.153`,`185.199.109.153`,`185.199.110.153`,`185.199.111.153`],se=[`2606:50c0:8000::153`,`2606:50c0:8001::153`,`2606:50c0:8002::153`,`2606:50c0:8003::153`],ce=new Set([`approved`,`issued`,`uploaded`]),le=new Set([`errored`,`bad_authz`,`authorization_revoked`]);function N(e,t,{apex:n,www:r}){let i=`${(e.split(`/`)[0]??``).toLowerCase()}.github.io`;return n?[...oe.map(e=>({type:`A`,name:t,value:e,purpose:`site`})),...se.map(e=>({type:`AAAA`,name:t,value:e,purpose:`site`,optional:!0})),...r?[{type:`CNAME`,name:`www.${t}`,value:i,purpose:`www`,optional:!0}]:[]]:[{type:`CNAME`,name:t,value:i,purpose:`site`}]}function ue(e,t){let n=`/repos/${t}/pages`;async function r(){let t=await D(e(),n,{allow:[404]});return t.status===404?void 0:await t.json()}async function i(t){try{await D(e(),n,{method:`PUT`,body:t})}catch(e){throw e instanceof E&&(e.status===403||e.status===404)?new v(`not-allowed`,`This sign-in can't change the site's GitHub Pages settings.`):e instanceof E&&(e.status===400||e.status===422)?/taken|already/i.test(e.message)?new v(`taken`,`Another GitHub Pages site already uses this domain.`):`https_enforced`in t?new v(`not-ready`,`The domain's certificate isn't ready yet.`):new v(`invalid`,`GitHub Pages doesn't accept this domain.`):e}}return{severalDomains:!1,async site(){let e=await r();return e&&{url:e.html_url,domain:e.cname??void 0}},async connect(e,n){return await i({cname:e}),N(t,e,n)},async records(e,n){return N(t,e,n)},async status(t){let r=await O(e(),n),i=r.https_certificate?.state??``;return{verified:!0,certificate:ce.has(i)?`ready`:le.has(i)?`failed`:`pending`,httpsOnly:r.https_enforced===!0,primary:r.cname===t}},async secure(){await i({https_enforced:!0})},async disconnect(){await i({cname:null})}}}var de=`.github/workflows/scheduled.yml`,fe=[`.github/workflows/deploy.yml`,`.github/workflows/rebuild.yml`];function pe(e){return{async timing(){let[t,...n]=await Promise.all([de,...fe].map(e));return t&&/\bdue\b/.test(t)&&/\bschedule:/.test(t)?`hourly`:n.some(e=>e&&/\bschedule:/.test(e))?`nightly`:`none`}}}function me(e){let t=new URL(e);return t.hostname===`api.github.com`?`https://github.com`:`${t.origin}${t.pathname.replace(/\/api\/v3\/?$/,``)}`.replace(/\/+$/,``)}function he(e,t,n,r={}){let i=r.wait??(e=>new Promise(t=>setTimeout(t,e))),s=(n,r)=>D(e,`/repos/${t}/contents/${n}?ref=${encodeURIComponent(r)}`,{allow:[404]}),c=async()=>(await s(`.github/workflows/${p}`,n)).ok;return{supported:c,secretsPlace:async()=>({kind:`github`,url:`${me(e.apiUrl)}/${t}/settings/secrets/actions/new`}),async run(n){let l=u(n);if(l)throw new f(`failed`,l);if(!await c())throw new f(`missing`,`The site's setup files don't run plugins' tasks: it needs plugin-task.yml.`);try{await D(e,`/repos/${t}/dispatches`,{method:`POST`,body:{event_type:a,client_payload:{request:n.id,plugin:n.plugin,task:n.task,input:n.input,key:n.key}}})}catch(e){throw e instanceof E&&(e.status===403||e.status===404)?new f(`not-allowed`,`Running plugins' tasks needs a sign-in that can publish to the site.`):e}let d=`${h}${n.id}`,p=Date.now()+(r.timeoutMs??3e5);for(;;){let n=await s(o,d);if(n.ok){let{content:r=``}=await n.json();return await D(e,`/repos/${t}/git/refs/heads/${encodeURIComponent(d)}`,{method:`DELETE`,allow:[404,422]}).catch(()=>{}),new TextDecoder().decode(S(r.replace(/\s/g,``)))}if(Date.now()>=p)throw new f(`timeout`,`The site's build service didn't answer in time.`);await i(r.pollMs??4e3)}}}}var ge=`deploy.yml`,_e=`update.yml`,ve=`publish-update`;function P(e,t,r,a,o,c=ge){let l=`/repos/${r}/actions/workflows/${c}`,u=`.github/workflows/${c}`;return{async setup(){let e=await o.read(u);return e&&/update --(publish|commit)\b/.test(e)?`ready`:`missing`},async lastRun(){let t=await D(e,`${l}/runs?branch=${encodeURIComponent(a)}&per_page=20`,{allow:[403,404]});if(!t.ok)return;let{workflow_runs:s=[]}=await t.json();for(let t of s.filter(e=>[`schedule`,`workflow_dispatch`].includes(e.event))){let a={date:t.created_at,detailsUrl:t.html_url};if(t.status!==`completed`)return{state:`running`,...a};let{jobs:s=[]}=await O(e,`/repos/${r}/actions/runs/${t.id}/jobs`),c=s.find(e=>e.name===`update`);if(!c||c.conclusion===`skipped`)continue;if(c.conclusion!==`success`)return{state:`failed`,...a};let l=s.find(e=>e.name===ve);if(l&&l.conclusion!==`success`&&l.conclusion!==`skipped`)return{state:`failed`,...a};let u=i(await o.readAt(`package.json`,t.head_sha)??``),d=i(await o.read(`package.json`)??``);if(!u||!d||u===d)return{state:`up-to-date`,...a};let f=n(d,u)<0;return{state:`updated`,...a,result:{state:`updated`,from:u,to:d,...f&&{rollback:f}}}}},nightly:ye(e,t,r,()=>o.read(u)),async rebuild(){await d({})},async start(e){await d({update:e})}};async function d(n){try{await D(t()??e,`${l}/dispatches`,{method:`POST`,body:{ref:a,inputs:n}})}catch(e){throw e instanceof E&&(e.status===403||e.status===401)?new s(`not-allowed`,`Running the site's build needs a token that can run its workflows.`):e instanceof E&&(e.status===404||e.status===422)?new s(`missing`,`The site's GitHub Pages workflow doesn't update Goodfellow.`):e}}}function ye(e,t,n,r){let i=`/repos/${n}/actions/variables`,a=e=>{throw e instanceof E&&(e.status===401||e.status===403)?new s(`not-allowed`,`Changing when the site rebuilds needs GitHub's Variables permission.`):e};return{async supported(){return(await r())?.includes(`GOODFELLOW_NIGHTLY`)??!1},async get(){let n=await D(t()??e,`${i}/${c}`,{allow:[403,404]});if(n.status===404)return`changed`;if(n.ok)return _((await n.json()).value)},async set(n){let r=t()??e;if(n===`changed`){await D(r,`${i}/${c}`,{method:`DELETE`,allow:[404]}).catch(a);return}let o={name:c,value:n};(await D(r,`${i}/GOODFELLOW_NIGHTLY`,{method:`PATCH`,body:o,allow:[404]}).catch(a)).status===404&&await D(r,i,{method:`POST`,body:o}).catch(a)}}}function F(e){return e instanceof C&&e.problem===`no-access`||e instanceof E&&(e.status===403||e.status===404)}function be(e){let{read:t}=e,n=k(e.repo),r,i=e=>(r??=O(e,`/repos/${n}`).then(e=>e.default_branch),r.catch(()=>{r=void 0}),r);async function a(){if(!t)throw new C(`no-access`,`This sign-in has no access to ${e.repo}.`);return e.open(t,await i(t))}async function o(e){let t=await a();return t.readAt(e,await t.revision())}async function s(){if(!t)throw new C(`no-access`,`This sign-in has no access to ${e.repo}.`);let r=await i(t);return P(t,e.manage,n,r,{read:o,readAt:async(e,t)=>(await a()).readAt(e,t)},_e)}return{code:{repo:e.repo,webUrl:`${e.webUrl}/${e.repo}`,read:o,history:async(e,t)=>(await a()).history(e,t),readAt:async(e,t)=>(await a()).readAt(e,t)},async setup(){try{return await(await s()).setup()}catch(e){if(F(e))return`no-access`;throw e}},async lastRun(){try{return await(await s()).lastRun()}catch(e){if(F(e))return;throw e}},async start(e){await(await s()).start(e)},async rebuild(){await(await s()).rebuild?.()}}}var I=/cloudflare/i,L=100,xe=`mutation ($input: CreateCommitOnBranchInput!) {
|
|
3
|
-
createCommitOnBranch(input: $input) { commit { oid } }
|
|
4
|
-
}`;function R(e,t){let n=`${t}/`;return[...e.keys()].filter(e=>e.startsWith(n)).sort()}var z=class n{user;pages;editors;ownerAccess;updates;drafts;scheduledBuilds;tasks;contentOnly;options;api;repo;branch;onSignOut;author;owner;pinned;trees=new Map;treeSizes=new Map;blobs=new Map;constructor(e){this.options=e,this.api=e.api,this.repo=k(e.repo),this.branch=e.branch,this.user=e.user,this.onSignOut=e.onSignOut,this.author=e.author,this.pinned=e.revision;let t=M(this.api,this.repo,e.ownerTokenLink,e.ownerRedirect);this.owner=t,this.ownerAccess=t.access,this.pages=ue(()=>t.api()??this.api,this.repo),this.editors=ae(this.api,t.api,this.repo,this.user.login),this.contentOnly=e.contentOnly===!0,this.contentOnly?e.code&&(this.updates=be({repo:e.code.repo,webUrl:e.code.webUrl,read:e.code.api,manage:t.codeApi,open:(t,r)=>new n({api:t,repo:e.code?.repo??``,branch:r,user:this.user,onSignOut:()=>{},ownerTokenLink:e.ownerTokenLink})})):this.updates=P(this.api,t.api,this.repo,this.branch,this),this.drafts=r(this,this.draftHost()),this.scheduledBuilds=pe(e=>this.read(e)),this.tasks=he(this.api,this.repo,this.branch,e.tasks)}async repositoryVisibility(){let e=await O(this.api,`/repos/${this.repo}`);return e.visibility===`internal`?`internal`:e.private===!1||e.visibility===`public`?`public`:`private`}draftHost(){let e=`/repos/${this.repo}`,t=t=>`${e}/git/refs/heads/${encodeURIComponent(t)}`,r=t=>{let n=decodeURIComponent(this.repo).split(`/`)[0],r=new URLSearchParams({head:`${n}:${t}`,state:`open`});return O(this.api,`${e}/pulls?${r}`)};return{liveBranch:this.branch,branchStore:e=>new n({...this.options,branch:e}),createBranch:async(t,n)=>{if((await D(this.api,`${e}/git/refs`,{method:`POST`,body:{ref:`refs/heads/${t}`,sha:n},allow:[422]})).status===422)throw new l(`exists`,`There's already a draft called ${t}.`)},deleteBranch:async e=>{await D(this.api,t(e),{method:`DELETE`,allow:[404,422]})},mergeBase:async t=>{let n=await D(this.api,`${e}/compare/${encodeURIComponent(this.branch)}...${encodeURIComponent(t)}`,{allow:[404]});if(n.status===404)throw new l(`not-found`,`There's no draft ${t}.`);return(await n.json()).merge_base_commit.sha},listBranches:async t=>(await O(this.api,`${e}/git/matching-refs/heads/${encodeURIComponent(t)}`)).map(e=>e.ref.replace(/^refs\/heads\//,``)),openReview:async({branch:t,title:n,description:i,reviewers:a=[]})=>{let o=await D(this.api,`${e}/pulls`,{method:`POST`,body:{title:n,head:t,base:this.branch,body:i},allow:[403,404,422]}),s;if(o.ok)s=await o.json();else if(o.status!==422)throw new l(`no-reviews`,`This sign-in can't open pull requests on the site's repository.`);else if([s]=await r(t),!s)throw new E(422,`GitHub couldn't open the pull request.`);for(let t of a)await D(this.api,`${e}/pulls/${s.number}/requested_reviewers`,{method:`POST`,body:{reviewers:[t]},allow:[403,404,422]});return{url:s.html_url}},listReviews:async t=>{let n=await O(this.api,`${e}/pulls?${new URLSearchParams({state:`open`,per_page:`100`})}`),r=decodeURIComponent(this.repo).toLowerCase();return n.filter(e=>e.head.ref.startsWith(t)&&(e.head.repo?.full_name??r).toLowerCase()===r).map(e=>({branch:e.head.ref,url:e.html_url,title:e.title}))},closeReview:async t=>{for(let n of await r(t))await D(this.api,`${e}/pulls/${n.number}`,{method:`PATCH`,body:{state:`closed`},allow:[403,404,422]})}}}async revision(){return this.pinned=await this.head(),this.pinned}async head(){return(await O(this.api,`/repos/${this.repo}/git/ref/heads/${encodeURIComponent(this.branch)}`)).object.sha}tree(e){let t=this.trees.get(e);return t||(t=O(this.api,`/repos/${this.repo}/git/trees/${e}?recursive=1`).then(t=>{if(t.truncated)throw new E(413,`The repository has too many files for GitHub to list at once.`);let n=t.tree.filter(e=>e.type===`blob`);return this.treeSizes.set(e,new Map(n.flatMap(e=>e.size===void 0?[]:[[e.path,e.size]]))),new Map(n.map(e=>[e.path,e.sha]))}),t.catch(()=>this.trees.delete(e)),this.trees.set(e,t)),t}async currentTree(){return this.tree(this.pinned??await this.revision())}async read(e){return this.readFrom(await this.currentTree(),e)}readFrom(e,t){let n=e.get(t);if(!n)return Promise.resolve(void 0);let r=this.blobs.get(n);return r||(r=D(this.api,`/repos/${this.repo}/git/blobs/${n}`,{accept:`application/vnd.github.raw+json`}).then(e=>e.text()),r.catch(()=>this.blobs.delete(n)),this.blobs.set(n,r)),r}async readFiles(e){return this.readFilesFrom(await this.currentTree(),e)}async readFilesFrom(e,t){let n=t.flatMap(t=>{let n=e.get(t);return n?[[t,n]]:[]}),r=[...new Set(n.map(([,e])=>e).filter(e=>!this.blobs.has(e)))],[i,a]=decodeURIComponent(this.repo).split(`/`);for(let e=0;e<r.length;e+=L){let t=r.slice(e,e+L),n=t.map((e,t)=>`f${t}: object(oid: "${e}") { ... on Blob { text isBinary } }`),o=await O(this.api,`/graphql`,{method:`POST`,body:{query:`query ($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { ${n.join(` `)} } }`,variables:{owner:i,name:a}}});t.forEach((e,t)=>{let n=o.data?.repository?.[`f${t}`];n&&!n.isBinary&&typeof n.text==`string`&&this.blobs.set(e,Promise.resolve(n.text))})}let o=new Map;for(let[t]of n){let n=await this.readFrom(e,t);n!==void 0&&o.set(t,n)}return o}async readBytes(e){return this.bytesFrom(await this.currentTree(),e)}async bytesFrom(e,t){let n=e.get(t);if(!n)return;let r=await D(this.api,`/repos/${this.repo}/git/blobs/${n}`,{accept:`application/vnd.github.raw+json`});return new Uint8Array(await r.arrayBuffer())}async list(e){return R(await this.currentTree(),e)}filesAt(e){return{read:async t=>this.readFrom(await this.tree(e),t),readFiles:async t=>this.readFilesFrom(await this.tree(e),t),readBytes:async t=>this.bytesFrom(await this.tree(e),t),list:async t=>R(await this.tree(e),t)}}async fileSizes(e){let t=`${e}/`;await this.currentTree();let n=this.treeSizes.get(this.pinned??``)??new Map;return new Map([...n].filter(([e])=>e.startsWith(t)))}useOwnerSignIn(e,t,n){this.owner.useSignIn(e,t,n)}ownerSignInFailed(e){this.owner.failed(e)}async write(t,n){return this.contentOnly&&e(t),this.author?this.writeCommit(t,n,this.author):this.writeGraphQL(t,n)}async writeCommit(e,{message:n,expectedRevision:r},i){let a=await this.tree(r),o=`/repos/${this.repo}`,s=[];try{for(let t of e)if(`delete`in t)a.has(t.path)&&s.push({path:t.path,mode:`100644`,type:`blob`,sha:null});else if(`bytes`in t){let e=await O(this.api,`${o}/git/blobs`,{method:`POST`,body:{content:w(t.bytes),encoding:`base64`}});s.push({path:t.path,mode:`100644`,type:`blob`,sha:e.sha})}else s.push({path:t.path,mode:`100644`,type:`blob`,content:t.content});if(s.length===0)return{revision:r};let c=await O(this.api,`${o}/git/commits/${r}`),l=await O(this.api,`${o}/git/trees`,{method:`POST`,body:{base_tree:c.tree.sha,tree:s}}),u=await O(this.api,`${o}/git/commits`,{method:`POST`,body:{message:n,tree:l.sha,parents:[r],author:{...i,date:new Date().toISOString()}}});if((await D(this.api,`${o}/git/refs/heads/${encodeURIComponent(this.branch)}`,{method:`PATCH`,body:{sha:u.sha,force:!1},allow:[422]})).status===422)throw await this.revision()===r?new E(422,`GitHub couldn't save the changes.`):new t;return this.pinned=u.sha,{revision:u.sha}}catch(e){throw e instanceof E&&(e.status===403||e.status===404)?new C(`cant-publish`,`This sign-in can't publish to the site.`):e}}async writeGraphQL(e,{message:n,expectedRevision:r}){let i=await this.tree(r),a=e.flatMap(e=>`delete`in e?[]:[{path:e.path,contents:`bytes`in e?w(e.bytes):x(e.content)}]),o=e.flatMap(e=>`delete`in e&&i.has(e.path)?[{path:e.path}]:[]);if(a.length===0&&o.length===0)return{revision:r};let s=await O(this.api,`/graphql`,{method:`POST`,body:{query:xe,variables:{input:{branch:{repositoryNameWithOwner:decodeURIComponent(this.repo),branchName:this.branch},message:{headline:n},expectedHeadOid:r,fileChanges:{additions:a,deletions:o}}}}}),c=s.data?.createCommitOnBranch?.commit?.oid;if(c)return this.pinned=c,{revision:c};if(await this.revision()!==r)throw new t;let l=s.errors?.[0];throw l?.type===`FORBIDDEN`?new C(`cant-publish`,`This GitHub account can't publish to the site.`):new E(422,`GitHub couldn't save the changes: ${l?.message??`unknown error`}`)}async history(e,{page:t=1,perPage:n=20}={}){let r=new URLSearchParams({sha:this.pinned??await this.revision(),path:e,per_page:String(n),page:String(t)});return(await O(this.api,`/repos/${this.repo}/commits?${r}`)).map(e=>({revision:e.sha,date:e.commit.author?.date??``,author:e.commit.author?.name||e.author?.login||void 0,message:e.commit.message.split(`
|
|
5
|
-
`)[0]??``}))}async readAt(e,t){return this.readFrom(await this.tree(t),e)}async changedPaths(e,t){let n=await O(this.api,`/repos/${this.repo}/compare/${e}...${t}`);return[...new Set((n.files??[]).flatMap(e=>[e.filename,e.previous_filename??[]].flat()))]}async deployStatus(e){try{let t=(await O(this.api,`/repos/${this.repo}/deployments?sha=${e}&per_page=5`))[0];if(t){let[n]=await O(this.api,`/repos/${this.repo}/deployments/${t.id}/statuses?per_page=1`),r=n?.log_url||n?.target_url||void 0;switch(n?.state){case`success`:case`inactive`:return{state:`live`,detailsUrl:r};case`failure`:case`error`:{let t=await this.workflowRun(e);return{state:`failed`,detailsUrl:r,problem:t?await this.runProblem(t):{step:`deploy`}}}default:return{state:`building`,detailsUrl:r}}}let n=await this.cloudflareBuild(e);if(n)return n;let r=await this.workflowRun(e);if(r?.status===`completed`&&r.conclusion===`cancelled`){let t=await this.head();if(t!==e)return this.deployStatus(t)}if(r?.status===`completed`&&r.conclusion!==`success`&&r.conclusion!==`skipped`)return{state:`failed`,detailsUrl:r.html_url,problem:await this.runProblem(r)};if(r)return{state:`building`,detailsUrl:r.html_url};if((await O(this.api,`/repos/${this.repo}/deployments?per_page=1`)).length>0)return{state:`building`};let i=await this.parentOf(e);return{state:i&&await this.cloudflareBuild(i)?`building`:`unknown`}}catch(e){if(e instanceof E)return{state:`unknown`};throw e}}async cloudflareBuild(e){let t=await D(this.api,`/repos/${this.repo}/commits/${e}/check-runs?per_page=50`,{allow:[403,404]});if(t.ok){let{check_runs:e=[]}=await t.json(),n=e.find(e=>I.test(`${e.app?.slug??``} ${e.name}`));if(n){let e=n.details_url??n.html_url??void 0;return n.status===`completed`?n.conclusion===`success`||n.conclusion===`neutral`||n.conclusion===`skipped`?{state:`live`,detailsUrl:e}:{state:`failed`,detailsUrl:e,problem:{step:`build`,detail:n.output?.title??void 0}}:{state:`building`,detailsUrl:e}}}let n=await D(this.api,`/repos/${this.repo}/commits/${e}/statuses?per_page=50`,{allow:[403,404]});if(!n.ok)return;let r=(await n.json()).find(e=>I.test(e.context));if(!r)return;let i=r.target_url??void 0;return r.state===`success`?{state:`live`,detailsUrl:i}:r.state===`pending`?{state:`building`,detailsUrl:i}:{state:`failed`,detailsUrl:i,problem:{step:`build`,detail:r.description??void 0}}}async parentOf(e){let t=await D(this.api,`/repos/${this.repo}/commits/${e}`,{allow:[403,404,422]});if(t.ok)return(await t.json()).parents?.[0]?.sha}async workflowRun(e){let t=await D(this.api,`/repos/${this.repo}/actions/runs?head_sha=${e}&per_page=20`,{allow:[403,404]});if(!t.ok)return;let{workflow_runs:n=[]}=await t.json(),r=n.filter(e=>!e.path?.endsWith(`/${b}.yml`));return r.find(e=>/deploy|pages/i.test(`${e.path??``} ${e.name??``}`))??r[0]}async runProblem(e){let t=await D(this.api,`/repos/${this.repo}/actions/runs/${e.id}/jobs?per_page=50`,{allow:[403,404]}),n=(t.ok?(await t.json()).jobs??[]:[]).find(e=>e.conclusion===`failure`);if(!n)return{step:e.conclusion===`startup_failure`?`not-started`:`host`,detail:e.conclusion??void 0};let r=n.steps?.find(e=>e.conclusion===`failure`);return r?{step:y(r.name)??(/deploy/i.test(n.name)?`deploy`:`build`),detail:`${n.name}: ${r.name}`}:{step:`not-started`,detail:n.name}}signOut(){this.ownerAccess.forget(),this.onSignOut()}},Se={invalid:`invalid`,"no-access":`no-access`,"cant-publish":`cant-publish`,cancelled:`redirect-failed`,"not-installed":`not-installed`,"no-address":`no-address`,"wrong-address":`wrong-address`,"local-address":`local-address`,"not-owner":`not-owner`};function B(e){let t=Se[String(e.problem)]??`unavailable`,n=typeof e.installUrl==`string`&&/^https:\/\//.test(e.installUrl)?e.installUrl:void 0;return new C(t,`The sign-in service said: ${String(e.problem??`no answer`)}.`,n)}function V(e){let t;try{t=new URL(e).hostname.toLowerCase()}catch{return!0}return t===`localhost`||t.endsWith(`.localhost`)||t===`0.0.0.0`||t===`[::1]`||/^127(\.\d{1,3}){3}$/.test(t)}function H(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}async function U(){let e=H(crypto.getRandomValues(new Uint8Array(32))),t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return{verifier:e,challenge:H(new Uint8Array(t))}}function W(){if(typeof window<`u`)return{href:()=>window.location.href,assign:e=>window.location.assign(e),replace:e=>window.history.replaceState(window.history.state,``,e)}}var G=`goodfellow_sign_in`,K=`goodfellow_sign_in_error`,q=class{url;fetcher;constructor(e,t){this.url=e.replace(/\/$/,``),this.fetcher=t}async answer(e,t){let n;try{n=await this.fetcher(`${this.url}${e}`,t)}catch(e){throw new C(`unavailable`,`Couldn't reach the sign-in service: ${e.message}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw B(r);return r}post(e,t){return this.answer(e,{method:`POST`,headers:{"content-type":`text/plain`},body:JSON.stringify(t)})}async postAnswer(e,t){let n;try{n=await this.fetcher(`${this.url}${e}`,{method:`POST`,headers:{"content-type":`text/plain`},body:JSON.stringify(t)})}catch(e){throw new C(`unavailable`,`Couldn't reach the sign-in service: ${e.message}`)}return{ok:n.ok,body:await n.json().catch(()=>({}))}}async health(){if((await this.answer(`/health`)).ok!==!0)throw new C(`unavailable`,`The sign-in service isn't set up.`)}async check(e,t){await this.answer(`/github/check?${new URLSearchParams({repo:e,purpose:t})}`)}startUrl(e){let t=new URLSearchParams({purpose:e.purpose,...e.repo&&{repo:e.repo},return:e.back,challenge:e.challenge,remember:e.remember?`1`:`0`,...e.install&&{install:`1`}});return`${this.url}/github/start?${t}`}session(e,t,n){return this.post(`/github/session`,{grant:e,verifier:t,...n&&{code:n}})}token(e,t){return this.post(`/github/token`,{session:e,...t&&{code:t}})}};function J(e,t,n,r){let i=t,a;async function o({refresh:t=!1}={}){return(t||Date.parse(i.expiresAt)-3e5<Date.now())&&(a??=e.token(i.session,r).finally(()=>{a=void 0}),i=await a,n(i)),i.token}return{current:()=>i,token:o,async codeToken(e){if(await o(e),!i.code)throw new C(`no-access`,`The sign-in service gave no token for the code repository.`);return i.code.token}}}var Y=`main`;function X(e=`https://github.com`){let t=new URLSearchParams({name:`Goodfellow site setup`,description:`Create a Goodfellow site. It can be deleted once the site is created.`,expires_in:`7`,administration:`write`,contents:`write`,workflows:`write`,pages:`write`,secrets:`write`}),n=new URLSearchParams({scopes:`repo,workflow`,description:`Goodfellow site setup`});return{fineGrained:`${e}/settings/personal-access-tokens/new?${t}`,classic:`${e}/settings/tokens/new?${n}`}}function Z(e){let t=new Map;async function n(e,t){if(t.default_branch===Y)return;let n=`/repos/${k(t.full_name)}`,r=await O(e,`${n}/git/ref/heads/${t.default_branch}`);await D(e,`${n}/git/refs`,{method:`POST`,body:{ref:`refs/heads/${Y}`,sha:r.object.sha}}),await D(e,n,{method:`PATCH`,body:{default_branch:Y}}),await D(e,`${n}/git/refs/heads/${t.default_branch}`,{method:`DELETE`})}async function r(e,t){try{return(await O(e,`/repos/${k(t.full_name)}/pages`,{method:`POST`,body:{build_type:`workflow`}})).html_url}catch(e){if(e instanceof E&&[403,404,409,422].includes(e.status))return;throw e}}async function i(e,t,n){try{return await D(e,`/repos/${k(t.full_name)}/pages`,{method:`PUT`,body:{cname:n}}),!0}catch(e){if(e instanceof E&&[400,403,404,409,422].includes(e.status))return!1;throw e}}async function a(t,n,r){let i=`/repos/${k(n.full_name)}`,a=[];for(let e of r.files){if(`delete`in e)continue;if(`content`in e){a.push({path:e.path,mode:`100644`,type:`blob`,content:e.content});continue}let n=await O(t,`${i}/git/blobs`,{method:`POST`,body:{content:w(e.bytes),encoding:`base64`}});a.push({path:e.path,mode:`100644`,type:`blob`,sha:n.sha})}try{let n=await O(t,`${i}/git/trees`,{method:`POST`,body:{tree:a}}),o=await O(t,`${i}/git/commits`,{method:`POST`,body:{message:r.message,tree:n.sha,parents:[],...e.author&&{author:{...e.author,date:new Date().toISOString()}}}});await D(t,`${i}/git/refs/heads/${Y}`,{method:`PATCH`,body:{sha:o.sha,force:!0}})}catch(e){throw e instanceof E&&(e.status===403||e.status===404)?new g(`not-allowed`,`This sign-in can't write the site's files, or its build setup.`):e}}async function o(e,t){return(await D(e,`/repos/${k(t.full_name)}/rulesets`,{method:`POST`,body:{name:`Protect the published history`,target:`branch`,enforcement:`active`,conditions:{ref_name:{include:[`~DEFAULT_BRANCH`],exclude:[]}},rules:[{type:`non_fast_forward`},{type:`deletion`}]},allow:[403,404,422]})).ok}async function s(e){if(!e.private)return!0;let{newDeployKey:n,sealSecret:r}=await te(()=>import(`./deploy-keys-DAj2oX-N-DRd_HmOG.js`).then(e=>e.t),__vite__mapDeps([0,1]),import.meta.url);try{for(let{reader:i,read:a,secret:o}of e.links.reads){if(!o)continue;let s=e[i],c=e[a],l=t.get(s.toLowerCase()),u=t.get(c.toLowerCase());if(!l||!u)throw Error(`${s} and ${c} have to be created first.`);let d=await n(`goodfellow-${o.toLowerCase()}`);await D(u,`/repos/${k(c)}/keys`,{method:`POST`,body:{title:`${s}'s builds`,key:d.publicKey,read_only:!0}});let f=`/repos/${k(s)}/actions/secrets`,p=await O(l,`${f}/public-key`),m=await r(d.privateKey,S(p.key));await D(l,`${f}/${o}`,{method:`PUT`,body:{encrypted_value:w(m),key_id:p.key_id}})}return!0}catch(e){if(e instanceof E&&[403,404,422].includes(e.status))return!1;throw e}}return{user:e.user,owners:()=>e.owners(),isAvailable:(t,n)=>e.isAvailable(t,n),async createSite(c,l){let u=[];l?.(`repository`);let{repo:d,api:f,signInInstallUrl:p}=await e.create(c),m=async e=>(l?.(`connect`),s(e));await n(f,d);let h;return c.pages&&(l?.(`pages`),h=await r(f,d),h?c.domain&&(await i(f,d,c.domain)?h=`https://${c.domain}/`:u.push(`domain-unavailable`)):u.push(`pages-unavailable`)),t.set(d.full_name.toLowerCase(),f),c.link&&!await m(c.link)&&u.push(`connect-unavailable`),l?.(`files`),await a(f,d,c),l?.(`protection`),await o(f,d)||u.push(`protection-unavailable`),p&&u.push(`sign-in-not-installed`),{repo:d.full_name,webUrl:d.html_url,siteUrl:h,buildsUrl:`${d.html_url}/actions`,pagesUrl:c.pages?`${d.html_url}/settings/pages`:void 0,...p&&{signInInstallUrl:p},warnings:u}}}}async function Ce(e){let t=await O(e,`/user`);async function n(t,n){return(await D(e,`/repos/${k(`${t.path}/${n}`)}`,{allow:[404]})).status===404}return{user:{login:t.login,name:t.name??void 0,avatarUrl:t.avatar_url},async owners(){return[{path:t.login,name:t.name||t.login,kind:`personal`},...(await O(e,`/user/orgs?per_page=100`).catch(()=>[])).map(e=>({path:e.login,name:e.login,kind:`organization`}))]},isAvailable:n,async create(t){let r=t.owner.kind===`personal`?`/user/repos`:`/orgs/${encodeURIComponent(t.owner.path)}/repos`;if(!await n(t.owner,t.name))throw new g(`name-taken`,`There's already a repository called ${t.owner.path}/${t.name}.`);try{return{repo:await O(e,r,{method:`POST`,body:{name:t.name,private:t.private,description:t.description,auto_init:!0}}),api:e}}catch(e){throw e instanceof E&&e.status===422?new g(`name-invalid`,`GitHub can't use "${t.name}" as a repository name.`):e instanceof E&&(e.status===403||e.status===404)?new g(`not-allowed`,`This sign-in can't create repositories in ${t.owner.path}.`):e}}}}function we(e,t,n,r){let i=r.session;async function a(t,n){let r=await e.postAnswer(t,{session:i,...n});if(typeof r.body.session==`string`&&(i=r.body.session),!r.ok)throw Te(r.body);return r.body}let{user:o}=r;return{user:{login:o.login,name:o.name,avatarUrl:o.avatarUrl},author:{name:o.name||o.login,email:o.email},async owners(){let e=await a(`/github/setup/owners`,{});return(e.owners??[]).map(({installed:t,...n})=>({...n,...!t&&e.installUrl&&{installUrl:e.installUrl}}))},async isAvailable(e,t){return(await a(`/github/setup/available`,{owner:e.path,name:t})).available===!0},async create(e){if(e.owner.installUrl)throw new g(`not-installed`,`Goodfellow isn't installed on ${e.owner.path}.`,e.owner.installUrl);let r=await a(`/github/setup/repository`,{owner:e.owner.path,name:e.name,private:e.private,description:e.description,...e.more&&{more:!0}});if(!r.repo||!r.token)throw new C(`unavailable`,`The sign-in service didn't answer.`);return{repo:r.repo,api:{apiUrl:t,token:r.token,fetch:n},...r.editInstallUrl&&{signInInstallUrl:r.editInstallUrl}}}}}function Te(e){switch(e.problem){case`name-taken`:return new g(`name-taken`,`There's already a repository with that name.`);case`name-invalid`:return new g(`name-invalid`,`GitHub can't use that as a repository name.`);case`not-allowed`:return new g(`not-allowed`,`This sign-in can't create repositories there.`);case`not-installed`:return new g(`not-installed`,`Goodfellow isn't installed there.`,e.installUrl);default:return B(e)}}function Q(e={}){let t=(e.apiUrl??`https://api.github.com`).replace(/\/$/,``),n=X(e.webUrl),r=e.fetch??((e,t)=>globalThis.fetch(e,t)),i=e.location??W(),a=e.signIn,o=a&&i&&!V(i.href())?new q(a,r):void 0,s=T(`goodfellow:github:setup:pending`,e.storage);return{name:`GitHub`,canRedirect:o!==void 0,tokenLinks:[{url:n.fineGrained,label:`signIn.token.create`},{url:n.classic,label:`signIn.token.createBroad`,hint:`signIn.token.createBroadHint`}],async restore(){if(!i)return null;let e=new URL(i.href()),n=e.searchParams.get(G),a=e.searchParams.get(K);if(!n&&!a)return null;e.searchParams.delete(G),e.searchParams.delete(K),i.replace(e.toString());let c=s.load();if(s.clear(),a||!n||!c||!o)throw B({problem:a??`cancelled`});let l=await o.session(n,c);return Z(we(o,t,r,l))},async signInWithToken(e){let n=e.trim();if(!n)throw new C(`invalid`,`Paste a token to sign in.`);return Z(await Ce({apiUrl:t,token:n,fetch:r}))},async startRedirect({install:e}={}){if(!o||!i)throw new C(`unavailable`,`Signing in with GitHub isn't available here.`);await o.health();let{verifier:t,challenge:n}=await U();s.save(t,!1),i.assign(o.startUrl({purpose:`setup`,back:i.href(),challenge:n,remember:!1,install:e}))}}}function Ee(e){return e instanceof C&&e.problem!==`unavailable`}function $(e,t=`https://github.com`){let[n=``]=e.split(`/`),r=new URLSearchParams({name:`Goodfellow admin`,description:`Edit ${e} in its admin panel`,target_name:n,expires_in:`90`,contents:`write`,deployments:`read`,actions:`read`,statuses:`read`}),i=new URLSearchParams({scopes:`repo`,description:`Goodfellow admin for ${e}`}),a=new URLSearchParams({name:`Goodfellow owner`,description:`Manage the editors, domain and updates of ${e}`,target_name:n,expires_in:`1`,administration:`write`,pages:`write`,actions:`write`,variables:`write`});return{fineGrained:`${t}/settings/personal-access-tokens/new?${r}`,classic:`${t}/settings/tokens/new?${i}`,owner:`${t}/settings/personal-access-tokens/new?${a}`}}function De(e){if(!/^[\w.-]+\/[\w.-]+$/.test(e.repo))throw Error(`github({ repo }) must look like "owner/name" (got "${e.repo}").`);if(e.code!==void 0&&!/^[\w.-]+\/[\w.-]+$/.test(e.code))throw Error(`github({ code }) must look like "owner/name" (got "${e.code}").`);let t=(e.apiUrl??`https://api.github.com`).replace(/\/$/,``),n=(e.webUrl??`https://github.com`).replace(/\/$/,``),r=t=>e.contentOnly&&e.code?{code:{repo:e.code,webUrl:n,...t&&{api:t}}}:{},i=$(e.repo,e.webUrl),a=T(`goodfellow:github:${e.repo}`,e.storage),o=T(`goodfellow:github:pending:${e.repo}`,e.storage),s=d(e.fetch??((e,t)=>globalThis.fetch(e,t)),{host:`GitHub`}),c=e.location??W(),l=e.signIn,u=l&&c&&!V(c.href())?new q(l,s):void 0,f=()=>e.contentOnly?e.code:void 0;function p(e,t){a.save(e.type===`token`?e.token:JSON.stringify(e),t)}function m(){let e=a.load();if(e){try{let t=JSON.parse(e);if(t.type===`worker`||t.type===`token`)return t}catch{}return{type:`token`,token:e}}}async function h(t,n,{install:r}={}){if(!u||!c)throw new C(`unavailable`,`Signing in with GitHub isn't available here.`);r||await u.check(e.repo,t);let{verifier:i,challenge:a}=await U();o.save(JSON.stringify({verifier:i,purpose:t,remember:n}),!1),c.assign(u.startUrl({purpose:t,repo:e.repo,back:c.href(),challenge:a,remember:n,install:r}))}async function g(n,o){let c=J(u,n,e=>p({type:`worker`,session:e.session},o),e.code);p({type:`worker`,session:n.session},o);let l={apiUrl:t,token:c.token,fetch:s},d=await O(l,`/repos/${k(e.repo)}`),{user:f}=n;return new z({api:l,repo:e.repo,branch:e.branch??d.default_branch,...e.contentOnly&&{contentOnly:!0},...r({apiUrl:t,token:c.codeToken,fetch:s}),user:{login:f.login,name:f.name,avatarUrl:f.avatarUrl},author:{name:f.name||f.login,email:f.email},onSignOut:()=>{a.clear(),v(c.current())},ownerTokenLink:{url:i.owner,label:`owner.token.create`},ownerRedirect:e=>h(`owner`,!1,e)})}function _(e){D({apiUrl:t,token:e,fetch:s},`/installation/token`,{method:`DELETE`}).catch(()=>{})}function v(e){_(e.token),e.code&&_(e.code.token)}async function y(e,t,n){let r=u;try{let i=J(r,await r.session(t,n,f()),()=>{},f());e.useOwnerSignIn(i.token,()=>v(i.current()),f()?i.codeToken:void 0)}catch(t){e.ownerSignInFailed(t)}}async function b(){if(!c)return;let e=new URL(c.href()),t=e.searchParams.get(G),n=e.searchParams.get(K);if(!t&&!n)return;e.searchParams.delete(G),e.searchParams.delete(K),c.replace(e.toString());let r=o.load();o.clear();let i=r?JSON.parse(r):void 0;if(!i||!u)throw new C(`redirect-failed`,`Signing in with GitHub didn't finish in this tab.`);if(i.purpose===`owner`){let e=await x();if(!e)throw new C(`redirect-failed`,`Sign in again, then sign in as an owner.`);return n?e.ownerSignInFailed(B({problem:n})):t&&await y(e,t,i.verifier),e}if(n||!t)throw B({problem:n});return g(await u.session(t,i.verifier,f()),i.remember)}async function x(){let e=m();if(!e)return null;try{return e.type===`token`?await S(e.token):u?await g(await u.token(e.session,f()),a.remembered()):(a.clear(),null)}catch(e){throw Ee(e)&&a.clear(),e}}async function S(n){let o={apiUrl:t,token:n,fetch:s},c=await O(o,`/user`),l;try{l=await O(o,`/repos/${k(e.repo)}`)}catch(t){throw t instanceof E&&(t.status===404||t.status===403)?new C(`no-access`,`The GitHub account ${c.login} can't see ${e.repo}.`):t}if(l.permissions?.push===!1)throw new C(`cant-publish`,`The GitHub account ${c.login} can see ${e.repo} but can't publish to it.`);return new z({api:o,repo:e.repo,branch:e.branch??l.default_branch,...e.contentOnly&&{contentOnly:!0},...r(o),user:{login:c.login,name:c.name??void 0,avatarUrl:c.avatar_url},onSignOut:()=>a.clear(),ownerTokenLink:{url:i.owner,label:`owner.token.create`},...u&&{ownerRedirect:e=>h(`owner`,!1,e)}})}function w({token:n}){let r={apiUrl:t,token:typeof n==`string`?n:()=>n(),fetch:s},a,o=()=>(a??=e.branch?Promise.resolve(e.branch):O(r,`/repos/${k(e.repo)}`).then(e=>e.default_branch),a.catch(()=>{a=void 0}),a),c=async(t,n)=>new z({api:r,repo:e.repo,branch:await o(),...e.contentOnly&&{contentOnly:!0},user:{login:n?.name??e.repo,...n&&{name:n.name}},onSignOut:()=>{},ownerTokenLink:{url:i.owner,label:`owner.token.create`},...t&&{revision:t},...n&&{author:n}});return{...e.contentOnly&&{contentOnly:!0},async revision(){return(await c()).revision()},at:c}}return{name:`GitHub`,source:ee(`@goodfellow-cms/github`,`github`,e,[`fetch`,`storage`,`location`]),canRedirect:u!==void 0,setup:()=>Q({...e.apiUrl&&{apiUrl:e.apiUrl},...e.webUrl&&{webUrl:e.webUrl},...e.fetch&&{fetch:e.fetch},...e.storage&&{storage:e.storage},...e.location&&{location:e.location},signIn:!1}),tokenLinks:[{url:i.fineGrained,label:`signIn.token.create`},{url:i.classic,label:`signIn.token.createBroad`,hint:`signIn.token.createBroadHint`}],async restore(){let e=await b();return e===void 0?x():e},async signInWithToken(e,t){let n=e.trim();if(!n)throw new C(`invalid`,`Paste a token to sign in.`);let r=await S(n);return p({type:`token`,token:n},t),r},startRedirect(e,t){return h(`edit`,e,t)},server:w}}export{z as GitHubBackend,De as github,N as githubPagesRecords,Q as githubSetup,X as githubSetupTokenLinks,$ as githubTokenLinks};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{n as e,r as t,t as n}from"./store-BtVaZcVF.js";import{a as r,d as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,r as f,s as ee,t as p,v as m}from"./setup-host-DQm73dc_.js";import{n as h,r as g,s as _,t as v}from"./git-eGyMXUIu.js";import{t as te}from"./scheduled-builds-BPfDaBYt.js";var ne=`bitbucket-pipelines.yml`,y=`VERCEL_DEPLOY_HOOK`,b={update:`update`,scheduled:`scheduled`,task:c,rebuild:`rebuild`},x={update:`0 17 4 * * ? *`};function re(e){return`0 ${e.getUTCMinutes()} ${e.getUTCHours()} ${e.getUTCDate()} ${e.getUTCMonth()+1} ? ${e.getUTCFullYear()}`}function S(e){let t=/^0 (\d{1,2}) (\d{1,2}) (\d{1,2}) (\d{1,2}) \? (\d{4})$/.exec(e.trim());if(!t)return;let[,n,r,i,a,o]=t.map(Number);return new Date(Date.UTC(o??0,(a??1)-1,i,r,n))}`${y}${y}${y}`;function C(e){return e.type===`api-token`?`Basic ${btoa(`${e.email}:${e.token}`)}`:`Bearer ${e.type===`oauth`?e.access:e.token}`}function w(e){let t=e.trim(),n=t.indexOf(`:`),r=t.slice(0,n);return n>0&&/^[^\s@:]+@[^\s@:]+$/.test(r)?{type:`api-token`,email:r,token:t.slice(n+1)}:{type:`token`,token:t}}async function ie(e){let t=await e.json().catch(()=>({})),n=t.error?.message??t.message;return typeof n==`string`?n:``}async function T(e,t,n={}){let r=t.startsWith(`https://`)||t.startsWith(`http://`)?t:`${e.apiUrl}${t}`,i=await e.fetch(r,{method:n.method??(n.body!==void 0||n.form?`POST`:`GET`),headers:{authorization:await e.authorization(),...n.body!==void 0&&{"content-type":`application/json`}},body:n.form??(n.body===void 0?void 0:JSON.stringify(n.body)),cache:`no-store`});if(i.status===401&&!n.allow?.includes(401))throw new h(`invalid`,`Bitbucket didn't accept the sign-in. It may have expired.`);if(!i.ok&&!n.allow?.includes(i.status)){let e=await ie(i);throw new v(i.status,`Bitbucket answered ${i.status}: ${e||i.statusText}`)}return i}async function E(e,t,n){return await(await T(e,t,n)).json()}async function D(e,t,n=20){let r=[],i=t;for(let t=0;i&&t<n;t++){let t=await E(e,i);r.push(...t.values),i=t.next}return r}function O(e){return`"${e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"`}async function k(e,t,n,r,i={}){return E(e,`/repositories/${t}/pipelines/`,{body:{target:{type:`pipeline_ref_target`,ref_type:`branch`,ref_name:n,selector:{type:`custom`,pattern:r}},variables:Object.entries(i).map(([e,t])=>({key:e,value:t,secured:!1}))}})}function A(e,t){return D(e,`/repositories/${t}/pipelines_config/schedules?pagelen=100`,5)}function j(e,t){return e.find(e=>e.target?.selector?.pattern===t)}function ae(e,t,n){return`${e}/${t}/pipelines/results/${n.build_number??encodeURIComponent(n.uuid)}`}var M=`https://bitbucket.org`,N=`https://api.bitbucket.org/2.0`;function P(e){throw e instanceof h||e instanceof v&&(e.status===403||e.status===404)?new a(`not-allowed`,`Setting up updates on Bitbucket needs the repository's Admin permission: use an owner token.`):e}function F(e){return e instanceof v&&(e.status===403||e.status===404)}function I(e,t,n,r,i){let{update:s}=b,c=`/repositories/${n}/pipelines_config`,l=()=>t()??e;async function u(){return j(await A(l(),n),s)}async function d(){return D(l(),`${c}/variables?pagelen=100`,5)}return{async setup(){if(!(await i())?.includes(`update --publish`))return`missing`;try{let[e,t]=await Promise.all([E(l(),c),A(l(),n)]);return e.enabled&&j(t,s)?`ready`:`needs-setup`}catch(e){if(F(e))return`needs-setup`;throw e}},async enable(){(await E(l(),c).catch(P)).enabled||await T(l(),c,{method:`PUT`,body:{enabled:!0}}).catch(P),!j(await A(l(),n).catch(P),s)&&await T(l(),`${c}/schedules`,{body:{type:`pipeline_schedule`,enabled:!0,cron_pattern:x.update,target:{type:`pipeline_ref_target`,ref_type:`branch`,ref_name:r,selector:{type:`custom`,pattern:s}}}}).catch(P)},async lastRun(){let t=await E(e,`/repositories/${n}/pipelines/?${new URLSearchParams({"target.selector.pattern":s,sort:`-created_on`,pagelen:`10`})}`);for(let r of t.values){let t={date:r.created_on,detailsUrl:ae(M,n,r)};if(r.state?.name!==`COMPLETED`)return{state:`running`,...t};let i=`/repositories/${n}/pipelines/${encodeURIComponent(r.uuid)}/steps`,[a]=(await E(e,i)).values;if(!a)continue;let o;try{let t=await T(e,`${i}/${encodeURIComponent(a.uuid)}/log`,{allow:[404]});o=t.ok?await t.text():``}catch(e){if(e instanceof h)throw e;return{state:`unknown`,...t}}let s=m(o);if(s)return{state:s.state,result:s,...t}}},async start(e){await k(l(),n,r,s,{GOODFELLOW_UPDATE:e}).catch(P)},nightly:{async supported(){return(await i())?.includes(` nightly `)??!1},async get(){try{let e=await u();return e?e.enabled?(await d()).find(e=>e.key===`GOODFELLOW_NIGHTLY`)?.value===`always`?`always`:`changed`:`off`:void 0}catch(e){if(F(e))return;throw e}},async set(e){let t=await u().catch(P);if(!t)throw new a(`missing`,`The site has no nightly schedule yet: turn on updates first.`);await T(l(),`${c}/schedules/${encodeURIComponent(t.uuid)}`,{method:`PUT`,body:{enabled:e!==`off`}}).catch(P);let n=(await d().catch(P)).find(e=>e.key===o);e===`always`&&n?await T(l(),`${c}/variables/${encodeURIComponent(n.uuid)}`,{method:`PUT`,body:{key:o,value:`always`,secured:!1}}).catch(P):e===`always`?await T(l(),`${c}/variables`,{body:{key:o,value:`always`,secured:!1}}).catch(P):n&&await T(l(),`${c}/variables/${encodeURIComponent(n.uuid)}`,{method:`DELETE`,allow:[404]}).catch(P)}},async rebuild(){await k(l(),n,r,s,{GOODFELLOW_REBUILD:`true`}).catch(P)}}}function L(e){return e instanceof h&&e.problem===`no-access`||e instanceof v&&(e.status===403||e.status===404)}function oe(e,t,n,r){let i,a=()=>(i??=E(e,`/repositories/${n}`).then(e=>e.mainbranch?.name??`main`),i.catch(()=>{i=void 0}),i);async function o(){return r(await a())}async function s(e){let t=await o();return t.readAt(e,await t.revision())}async function c(){return I(e,t,n,await a(),()=>s(ne))}return{code:{repo:n,webUrl:`${M}/${n}`,read:s,history:async(e,t)=>(await o()).history(e,t),readAt:async(e,t)=>(await o()).readAt(e,t)},async setup(){try{return await(await c()).setup()}catch(e){if(L(e))return`no-access`;throw e}},async enable(){await(await c()).enable?.()},async lastRun(){try{return await(await c()).lastRun()}catch(e){if(L(e))return;throw e}},async start(e){await(await c()).start(e)},async rebuild(){await(await c()).rebuild?.()}}}function R(e){return e===`admin`?`owner`:e===`write`?`editor`:`viewer`}function z(e){return e===`owner`?`admin`:`write`}function B(e){return e instanceof v&&(e.status===403||e.status===404)}function se(e,t){let n=t.toLowerCase();return[e.nickname,e.display_name,e.account_id,e.uuid].some(e=>e?.toLowerCase()===n)}function ce(e,t,n,r,i){let a=`/repositories/${n}/permissions-config/users`,o=n.split(`/`)[0]??``;function s(){let n=t()??(i===`admin`?e:void 0);if(!n)throw new f(`not-allowed`,`Changing editors on Bitbucket needs an owner token.`);return n}async function c(e){try{await e(s())}catch(e){throw e instanceof f?e:B(e)?new f(`not-allowed`,`This token can't change the site's editors.`):e}}async function l(e,t){if(t.includes(`@`)){let n=new URLSearchParams({q:`user.email IN (${O(t)})`});return(await E(e,`/workspaces/${o}/members?${n}`).catch(()=>void 0))?.values[0]?.user}return(await D(e,`/workspaces/${o}/members?pagelen=100`,10)).map(e=>e.user).find(e=>se(e,t))}return{invitesByEmail:!1,membersOnly:!0,async list(){let n=t()??e,o;try{o=await D(n,`${a}?pagelen=100`,10)}catch(e){if(!B(e))throw e;return{editors:[{id:r.login,login:r.login,name:r.name,role:R(i??`write`),self:!0}],manage:i===`admin`?`token`:`no`,editorsCanPublish:!0}}return{editors:o.filter(e=>e.permission!==`none`).map(e=>({id:e.user.uuid,login:e.user.nickname,name:e.user.display_name,avatarUrl:e.user.links?.avatar?.href,role:R(e.permission),...e.user.nickname?.toLowerCase()===r.login.toLowerCase()&&{self:!0}})),manage:t()||i===`admin`?`yes`:`no`,editorsCanPublish:!0}},async invite(e,t){let n=e.trim().replace(/^@/,``);if(!n||/\s{2,}|[/\\]/.test(n))throw new f(`invalid`,`That isn't a Bitbucket account name or email address.`);let r=s(),i=await l(r,n);if(!i)throw new f(`not-found`,`Nobody called ${n} is in the Bitbucket workspace ${o}: add them to the workspace on Bitbucket first.`);let c=`${a}/${encodeURIComponent(i.uuid)}`,u=await T(r,c,{allow:[403,404]});if(u.ok&&(await u.json()).permission!==`none`)throw new f(`already`,`${n} already edits the site.`);let d=await T(r,c,{method:`PUT`,body:{permission:z(t)},allow:[400,402,403,404]});if(!d.ok)throw d.status===402?new f(`invalid`,`The Bitbucket workspace's plan has as many users as it allows.`):d.status===400?new f(`invalid`,`Bitbucket didn't accept ${n}.`):new f(`not-allowed`,`This token can't change the site's editors.`)},async setRole(e,t){await c(n=>T(n,`${a}/${encodeURIComponent(e.id)}`,{method:`PUT`,body:{permission:z(t)}}))},async remove(e){await c(t=>T(t,`${a}/${encodeURIComponent(e.id)}`,{method:`DELETE`,allow:[404]}))}}}function V(e,t,n){let r;return{access:{tokenLink:n,get active(){return r!==void 0},async applyToken(n){let i=w(n),a={...e,authorization:async()=>C(i)};try{await E(a,`/repositories/${t}/permissions-config/users?pagelen=1`)}catch(e){throw e instanceof h||B(e)?new f(`not-allowed`,`This token can't change the site's editors.`):e}r=a},forget(){r=void 0}},api:()=>r}}var H=`name: Scheduled change`;function U(e){return e instanceof v&&(e.status===401||e.status===403)}function W(e){throw U(e)?new te(`not-allowed`,`Adding Pipelines schedules on Bitbucket needs permission to change the repository's Pipelines settings.`):e}function G(e){return e.toISOString().slice(0,16)}function le(e,t,n,r,i,a=()=>new Date){let{scheduled:o}=b,s=`/repositories/${n}/pipelines_config/schedules`;return{async timing(){let e=await i().catch(()=>void 0);return e?.includes(H)?`exact`:e?.includes(` nightly `)?`nightly`:`none`},async sync(i){let c=t()??e,l=a(),u=new Map;for(let e of[...i].filter(e=>e>l).sort((e,t)=>e.getTime()-t.getTime())){if(u.size>=50)break;u.set(G(e),e)}let d=new Map;for(let e of await A(c,n).catch(W)){if(e.target?.selector?.pattern!==o)continue;let t=S(e.cron_pattern);t&&d.set(G(t),e)}for(let[e,t]of d)u.has(e)||await T(c,`${s}/${encodeURIComponent(t.uuid)}`,{method:`DELETE`,allow:[403,404]});for(let[e,t]of u)d.has(e)||await E(c,s,{body:{type:`pipeline_schedule`,enabled:!0,cron_pattern:re(t),target:{type:`pipeline_ref_target`,ref_type:`branch`,ref_name:r,selector:{type:`custom`,pattern:o}}}}).catch(W)}}}function ue(e,t,n,r,a={}){let o=a.wait??(e=>new Promise(t=>setTimeout(t,e))),s=async()=>(await r().catch(()=>void 0)??``).includes(`GOODFELLOW_TASK_PLUGIN`);return{supported:s,secretsPlace:async()=>({kind:`bitbucket`,url:`${M}/${t}/admin/pipelines/repository-variables`}),async run(r){let c=l(r);if(c)throw new d(`failed`,c);if(!await s())throw new d(`missing`,`The site's setup files don't run plugins' tasks: bitbucket-pipelines.yml needs the plugin-task pipeline.`);let u;try{u=await k(e,t,n,b.task,{GOODFELLOW_TASK_REQUEST:r.id,GOODFELLOW_TASK_PLUGIN:r.plugin,GOODFELLOW_TASK_NAME:r.task,GOODFELLOW_TASK_INPUT:r.input,GOODFELLOW_TASK_KEY:r.key})}catch(e){throw e instanceof v&&e.status===400?new d(`missing`,`The site's repository doesn't have Bitbucket Pipelines turned on.`):e instanceof v&&(e.status===403||e.status===404)?new d(`not-allowed`,`Running plugins' tasks needs a sign-in that can run the site's pipelines.`):e}let f=`${ee}${r.id}`,p=`/repositories/${t}/pipelines/${encodeURIComponent(u.uuid)}`,m=Date.now()+(a.timeoutMs??3e5),g=!1;for(;;){let n=await T(e,`/repositories/${t}/src/${encodeURIComponent(f)}/${i}`,{allow:[404]});if(n.ok){let r=await n.text();return await T(e,`/repositories/${t}/refs/branches/${encodeURIComponent(f)}`,{method:`DELETE`,allow:[403,404]}).catch(()=>{}),r}if(g)throw new d(`failed`,`The site's build service couldn't run the task.`);if(g=(await E(e,p).catch(e=>{if(e instanceof h)throw e}))?.state?.name===`COMPLETED`,!g){if(Date.now()>=m)throw new d(`timeout`,`The site's build service didn't answer in time.`);await o(a.pollMs??4e3)}}}}}var de=10,K=8;function q(e){return!(e.url??``).startsWith(`${M}/`)}function J(e){return e.split(`/`).map(encodeURIComponent).join(`/`)}function Y(e,t){let n=`${t}/`;return[...e.keys()].filter(e=>e.startsWith(n)).sort()}function X(e){return(e??``).split(`
|
|
2
|
-
`)[0]?.trim()??``}function fe(e){return e.author?.user?.display_name||e.author?.raw?.replace(/\s*<[^>]*>\s*$/,``).trim()||void 0}var Z=class i{user;editors;ownerAccess;updates;drafts;scheduledBuilds;tasks;contentOnly;options;api;repo;branch;onSignOut;owner;pinned;trees=new Map;texts=new Map;constructor(e){this.options=e,this.api=e.api,this.repo=e.repo,this.branch=e.branch,this.user=e.user,this.onSignOut=e.onSignOut,this.pinned=e.revision,this.contentOnly=e.contentOnly===!0,this.owner=V(this.api,this.repo,e.ownerTokenLink??{url:`https://bitbucket.org/${this.repo}/admin/access-tokens`,label:`owner.token.create`}),this.ownerAccess=this.owner.access;let t=async()=>this.readAt(`bitbucket-pipelines.yml`,this.pinned??await this.revision());if(this.editors=ce(this.api,this.owner.api,this.repo,this.user,e.permission),!this.contentOnly)this.updates=I(this.api,this.owner.api,this.repo,this.branch,t);else if(e.code){let t=e.code;this.updates=oe(this.api,this.owner.api,t,e=>new i({api:this.api,repo:t,branch:e,user:this.user,onSignOut:()=>{}}))}this.drafts=r(this,this.draftHost()),this.scheduledBuilds=le(this.api,this.owner.api,this.repo,this.branch,t),this.tasks=ue(this.api,this.repo,this.branch,t,e.tasks)}path(e){return`/repositories/${this.repo}${e}`}async repositoryVisibility(){let{is_private:e}=await E(this.api,this.path(``));return e===!1?`public`:`private`}draftHost(){let e=async e=>{let t=await T(this.api,this.path(`/refs/branches/${encodeURIComponent(e)}`),{allow:[404]});if(t.ok)return(await t.json()).target.hash},t=async e=>{let t=new URLSearchParams({q:`source.branch.name = ${O(e)} AND state = "OPEN"`});return(await E(this.api,this.path(`/pullrequests?${t}`))).values},n=async e=>{let t=this.repo.split(`/`)[0]??``,n=await D(this.api,`/workspaces/${t}/members?pagelen=100`,10).catch(()=>[]);return e.flatMap(e=>{let t=n.find(t=>t.user.nickname?.toLowerCase()===e.toLowerCase());return t?.user.account_id?[{account_id:t.user.account_id}]:[]})};return{liveBranch:this.branch,branchStore:e=>new i({...this.options,branch:e,revision:void 0}),createBranch:async(t,n)=>{let r=await T(this.api,this.path(`/refs/branches`),{body:{name:t,target:{hash:n}},allow:[400,409]});if(!r.ok)throw await e(t)?new s(`exists`,`There's already a draft called ${t}.`):new v(r.status,`Bitbucket couldn't make the branch ${t}.`)},deleteBranch:async e=>{await T(this.api,this.path(`/refs/branches/${encodeURIComponent(e)}`),{method:`DELETE`,allow:[404]})},mergeBase:async t=>{let[n,r]=await Promise.all([e(t),e(this.branch)]);if(!n||!r)throw new s(`not-found`,`There's no draft ${t}.`);return(await E(this.api,this.path(`/merge-base/${n}..${r}`))).hash},listBranches:async e=>{let t=new URLSearchParams({q:`name ~ ${O(e)}`,pagelen:`100`});return(await D(this.api,this.path(`/refs/branches?${t}`),5)).map(e=>e.name).filter(t=>t.startsWith(e))},openReview:async({branch:e,title:r,description:i,reviewers:a=[]})=>{let o=t=>T(this.api,this.path(`/pullrequests`),{body:{title:r,description:i,source:{branch:{name:e}},destination:{branch:{name:this.branch}},close_source_branch:!0,...t.length>0&&{reviewers:t}},allow:[400,403,404]}),c=await n(a.filter(e=>e.toLowerCase()!==this.user.login.toLowerCase())),l=await o(c);if(l.status===400&&c.length>0&&(l=await o([])),l.ok)return{url:(await l.json()).links.html.href};if(l.status!==400)throw new s(`no-reviews`,`This sign-in can't open pull requests on the site's repository.`);let[u]=await t(e);if(!u)throw new s(`no-reviews`,`Bitbucket couldn't open the pull request.`);return{url:u.links.html.href}},listReviews:async e=>{let t=new URLSearchParams({q:`source.branch.name ~ ${O(e)} AND state = "OPEN"`,pagelen:`50`});return(await D(this.api,this.path(`/pullrequests?${t}`),5)).filter(t=>t.source.branch.name.startsWith(e)).map(e=>({branch:e.source.branch.name,url:e.links.html.href,title:e.title}))},closeReview:async e=>{for(let n of await t(e))await T(this.api,this.path(`/pullrequests/${n.id}/decline`),{body:{},allow:[400,403,404]})}}}async revision(){let e=this.pinned;if(this.pinned=await this.head(),e&&e!==this.pinned&&this.hasTextsAt(e)){let t=await this.changedPaths(e,this.pinned).catch(()=>void 0);t&&this.carryOver(e,this.pinned,new Set(t))}return this.pinned}async head(){return(await E(this.api,this.path(`/refs/branches/${encodeURIComponent(this.branch)}`))).target.hash}hasTextsAt(e){for(let t of this.texts.keys())if(t.startsWith(`${e}:`))return!0;return!1}carryOver(e,t,n){for(let[r,i]of[...this.texts]){if(!r.startsWith(`${e}:`))continue;let a=r.slice(e.length+1);!n.has(a)&&!this.texts.has(`${t}:${a}`)&&this.texts.set(`${t}:${a}`,i)}}async listFolder(e,t){let n=new URLSearchParams({max_depth:String(de),pagelen:`100`}),r=await T(this.api,this.path(`/src/${e}/${J(t)}/?${n}`),{allow:[404]});if(r.status===404)return[];let i=[],a=await r.json();for(;;){for(let e of a.values)e.type===`commit_file`&&i.push([e.path,e.size??0]);if(!a.next)return i;a=await E(this.api,a.next)}}tree(t){let n=this.trees.get(t);return n||(n=Promise.all(e.map(e=>this.listFolder(t,e))).then(e=>new Map(e.flat())),n.catch(()=>this.trees.delete(t)),this.trees.set(t,n)),n}async current(){return this.pinned??await this.revision()}async read(e){let t=await this.current();return this.readFrom(t,await this.tree(t),e)}readFrom(e,t,n){if(!t.has(n))return Promise.resolve(void 0);let r=`${e}:${n}`,i=this.texts.get(r);return i||(i=T(this.api,this.path(`/src/${e}/${J(n)}`)).then(e=>e.text()),i.catch(()=>this.texts.delete(r)),this.texts.set(r,i)),i}async readFiles(e){let t=await this.current();return this.readFilesFrom(t,await this.tree(t),e)}async readFilesFrom(e,t,n){let r=new Map,i=n.filter(e=>t.has(e));for(let n=0;n<i.length;n+=K){let a=i.slice(n,n+K),o=await Promise.all(a.map(n=>this.readFrom(e,t,n)));a.forEach((e,t)=>{let n=o[t];n!==void 0&&r.set(e,n)})}return r}async readBytes(e){let t=await this.current();return this.bytesFrom(t,await this.tree(t),e)}async bytesFrom(e,t,n){if(!t.has(n))return;let r=await T(this.api,this.path(`/src/${e}/${J(n)}`));return new Uint8Array(await r.arrayBuffer())}async list(e){return Y(await this.tree(await this.current()),e)}filesAt(e){return{read:async t=>this.readFrom(e,await this.tree(e),t),readFiles:async t=>this.readFilesFrom(e,await this.tree(e),t),readBytes:async t=>this.bytesFrom(e,await this.tree(e),t),list:async t=>Y(await this.tree(e),t)}}async fileSizes(e){let t=await this.tree(await this.current());return new Map(Y(t,e).map(e=>[e,t.get(e)??0]))}async existsAt(t,n,r){return e.some(e=>n.startsWith(`${e}/`))?t.has(n):(await T(this.api,this.path(`/src/${r}/${J(n)}?format=meta`),{allow:[404]})).ok}async write(e,{message:r,expectedRevision:i}){this.contentOnly&&t(e);let a=await this.tree(i),o=new FormData,s=0;for(let t of e){if(`delete`in t){if(!await this.existsAt(a,t.path,i))continue;o.append(`files`,t.path)}else{let e=`bytes`in t?new Uint8Array(t.bytes):t.content;o.append(`/${t.path}`,new Blob([e]),t.path.split(`/`).at(-1)??t.path)}s+=1}if(s===0)return{revision:i};o.append(`message`,r),o.append(`branch`,this.branch),o.append(`parents`,i),this.options.author&&o.append(`author`,`${this.options.author.name} <${this.options.author.email}>`);let c=await T(this.api,this.path(`/src`),{form:o,allow:[403,409]});if(c.status===409)throw new n;if(c.status===403)throw new h(`cant-publish`,`This Bitbucket account can't publish to the site.`);let l=await this.commitAfter(i,r);return this.carryOver(i,l,new Set(e.map(e=>e.path))),this.pinned=l,{revision:l}}async commitAfter(e,t){let n=new URLSearchParams({pagelen:`20`}),r=await E(this.api,this.path(`/commits/${encodeURIComponent(this.branch)}?${n}`)),i=r.values.find(n=>n.parents?.[0]?.hash===e&&X(n.message)===X(t))??r.values.find(t=>t.parents?.[0]?.hash===e);return i?i.hash:this.head()}async history(e,{page:t=1,perPage:n=20}={}){let r=new URLSearchParams({path:e,pagelen:String(n)}),i=this.path(`/commits/${await this.current()}?${r}`),a={values:[]};for(let e=1;i&&e<=t;e++)if(a=await E(this.api,i),i=a.next,e<t&&!i)return[];return a.values.map(e=>({revision:e.hash,date:e.date??``,author:fe(e),message:X(e.message)}))}async readAt(e,t){let n=await T(this.api,this.path(`/src/${t}/${J(e)}`),{allow:[404]});return n.ok?n.text():void 0}async changedPaths(e,t){let n=new URLSearchParams({topic:`false`,pagelen:`500`}),r=(await D(this.api,this.path(`/diffstat/${t}..${e}?${n}`))).flatMap(e=>[e.old?.path,e.new?.path]);return[...new Set(r.filter(e=>!!e))]}async deployStatus(e){try{let t=await this.statuses(e),n=t.filter(q);if(n.length===0){if(t.length>0)return{state:`unknown`};let n=(await E(this.api,this.path(`/commit/${e}`))).parents?.[0]?.hash;return{state:(n?(await this.statuses(n)).filter(q):[]).length>0?`building`:`unknown`}}let r=n.find(e=>e.state===`FAILED`)??n.find(e=>e.state===`STOPPED`);if(r?.state===`STOPPED`){let t=await this.head();if(t!==e)return this.deployStatus(t)}if(r)return{state:`failed`,...r.url&&{detailsUrl:r.url}};let i=n[0]?.url;return{state:n.every(e=>e.state===`SUCCESSFUL`)?`live`:`building`,...i&&{detailsUrl:i}}}catch(e){if(e instanceof v)return{state:`unknown`};throw e}}statuses(e){return D(this.api,this.path(`/commit/${e}/statuses?pagelen=100`),3)}signOut(){this.ownerAccess.forget(),this.onSignOut()}},Q=`main`,pe=/^[a-z0-9][a-z0-9_.-]{0,61}$/;function $(e={}){let t=e.fetch??((e,t)=>globalThis.fetch(e,t));async function n(e){let n={apiUrl:N,authorization:async()=>C(e),fetch:t},r=await E(n,`/user`,{allow:[403]}).catch(e=>{throw e instanceof v?new h(`invalid`,`Creating a repository on Bitbucket needs an API token, not an access token.`):e}),i=r.username??r.nickname??``;if(!i)throw new h(`invalid`,`Creating a repository on Bitbucket needs an API token, not an access token.`);return{user:{login:i,name:r.display_name},owners:async()=>{let e=await D(n,`/user/workspaces?pagelen=100`,5);return e.filter(t=>t.permission!==`member`||e.length===1).map(({workspace:e})=>({path:e.slug,name:e.name??e.slug,kind:e.slug===i?`personal`:`organization`})).sort((e,t)=>e.kind===t.kind?e.name.localeCompare(t.name):e.kind===`personal`?-1:1)},async isAvailable(e,t){return(await T(n,`/repositories/${e.path}/${t.toLowerCase()}`,{allow:[403,404]})).status===404},async createSite(e,t){let r=e.name.toLowerCase();if(!pe.test(r))throw new p(`name-invalid`,`That name can't be used for a repository.`);let i=`${e.owner.path}/${r}`;t?.(`repository`);let a=await T(n,`/repositories/${i}`,{body:{scm:`git`,is_private:e.private,...e.description&&{description:e.description}},allow:[400,403]});if(a.status===400)throw new p(`name-taken`,`There's already a repository called ${i}.`);if(a.status===403)throw new p(`not-allowed`,`This account can't create repositories in ${e.owner.name}.`);t?.(`files`);let o=new FormData;for(let t of e.files){if(`delete`in t)continue;let e=`bytes`in t?new Uint8Array(t.bytes):t.content;o.append(`/${t.path}`,new Blob([e]),t.path.split(`/`).at(-1)??t.path)}if(o.append(`message`,e.message),o.append(`branch`,Q),(await T(n,`/repositories/${i}/src`,{form:o,allow:[403]})).status===403)throw new p(`not-allowed`,`This account can't write to the new repository.`);await T(n,`/repositories/${i}`,{method:`PUT`,body:{mainbranch:{name:Q}},allow:[400,403]});let s=e.pages?[`pages-unavailable`]:[];return{repo:i,webUrl:`${M}/${i}`,buildsUrl:`${M}/${i}/pipelines`,warnings:s}}}}return{name:`Bitbucket`,canRedirect:!1,tokenLinks:[{url:`https://id.atlassian.com/manage-profile/security/api-tokens`,label:`signIn.token.create`,hint:`signIn.token.apiTokenHint`}],async restore(){return null},async signInWithToken(e){let t=e.trim();if(!t)throw new h(`invalid`,`Paste a token to sign in.`);return n(w(t))},async startRedirect(){throw Error(`Creating repositories on Bitbucket needs a token.`)}}}function me(){return{href:()=>window.location.href,assign:e=>window.location.assign(e),replace:e=>window.history.replaceState(window.history.state,``,e)}}function he(){return[...crypto.getRandomValues(new Uint8Array(16))].map(e=>e.toString(16).padStart(2,`0`)).join(``)}function ge(e){let t=u(e.fetch??((e,t)=>globalThis.fetch(e,t)),{host:`Bitbucket`}),n=g(`goodfellow:bitbucket:${e.repo}`,e.storage),r=g(`goodfellow:bitbucket:pending:${e.repo}`,e.storage),i=()=>e.location??me(),[a=``]=e.repo.split(`/`);async function o(r,i){if(r.type===`oauth`&&r.expiresAt<Date.now())throw new h(`invalid`,`The Bitbucket sign-in has expired.`);let o={apiUrl:N,authorization:async()=>C(r),fetch:t},s=await T(o,`/repositories/${e.repo}`,{allow:[403,404]});if(!s.ok)throw new h(`no-access`,`This Bitbucket sign-in can't see ${e.repo}.`);let c=await s.json(),l=await T(o,`/user`,{allow:[401,403]}),u=l.ok?await l.json():void 0,d=u?.username??u?.nickname,f;if(d){let t=new URLSearchParams({q:`repository.full_name = ${O(e.repo)}`});if(f=await E(o,`/user/workspaces/${a}/permissions/repositories?${t}`).then(e=>e.values[0]?.permission,()=>void 0),f===`read`)throw new h(`cant-publish`,`The Bitbucket account ${d} can see ${e.repo} but can't publish to it.`)}return n.save(JSON.stringify(r),i),new Z({api:o,repo:e.repo,branch:e.branch??c.mainbranch?.name??`main`,user:d?{login:d,name:u?.display_name,avatarUrl:u?.links?.avatar?.href}:{login:`access-token`,name:`Access token`},...f&&{permission:f},...e.contentOnly&&{contentOnly:!0,...e.code&&{code:e.code}},onSignOut:()=>n.clear()})}async function s(){let e=new URL(i().href()),t=new URLSearchParams(e.hash.replace(/^#/,``)),n=t.get(`access_token`),a=t.get(`error`)??e.searchParams.get(`error`);if(!n&&!a)return null;let s=r.load();if(!s)return null;r.clear();let c=JSON.parse(s);e.hash=c.hash;for(let t of[`error`,`error_description`])e.searchParams.delete(t);if(i().replace(e.toString()),a||!n||t.get(`state`)!==c.state)throw new h(`redirect-failed`,`Signing in with Bitbucket was cancelled or didn't finish.`);let l=Number(t.get(`expires_in`)??7200);return o({type:`oauth`,access:n,expiresAt:Date.now()+(Number.isFinite(l)?l:7200)*1e3},c.remember)}function c({token:n}){let r={apiUrl:N,authorization:async()=>C(w(typeof n==`string`?n:await n())),fetch:t},i,a=()=>(i??=e.branch?Promise.resolve(e.branch):E(r,`/repositories/${e.repo}`).then(e=>e.mainbranch?.name??`main`),i.catch(()=>{i=void 0}),i),o=async(t,n)=>new Z({api:r,repo:e.repo,branch:await a(),...e.contentOnly&&{contentOnly:!0,...e.code&&{code:e.code}},user:{login:n?.name??e.repo,...n&&{name:n.name}},onSignOut:()=>{},...t&&{revision:t},...n&&{author:n}});return{...e.contentOnly&&{contentOnly:!0,...e.code&&{code:e.code}},async revision(){return(await o()).revision()},at:o}}return{name:`Bitbucket`,source:_(`@goodfellow-cms/bitbucket`,`bitbucket`,e,[`fetch`,`storage`,`location`]),canRedirect:!!e.clientId,redirectAddressesListed:!!e.clientId,setup:()=>$({...e.fetch&&{fetch:e.fetch}}),tokenLinks:[{url:`${M}/${e.repo}/admin/access-tokens`,label:`signIn.token.create`},{url:`https://id.atlassian.com/manage-profile/security/api-tokens`,label:`signIn.token.createBroad`,hint:`signIn.token.apiTokenHint`}],async restore(){let e=await s();if(e)return e;let t=n.load();if(!t)return null;try{return await o(JSON.parse(t),n.remembered())}catch(e){throw e instanceof h&&n.clear(),e}},async signInWithToken(e,t){let n=e.trim();if(!n)throw new h(`invalid`,`Paste a token to sign in.`);return o(w(n),t)},async startRedirect(t){if(!e.clientId)throw Error(`bitbucket({ clientId }) is needed to sign in with Bitbucket.`);let n=he(),a={state:n,remember:t,hash:new URL(i().href()).hash};r.save(JSON.stringify(a),!1);let o=new URLSearchParams({client_id:e.clientId,response_type:`token`,state:n});i().assign(`${M}/site/oauth2/authorize?${o}`)},server:c}}export{N as BITBUCKET_API,M as BITBUCKET_WEB,Z as BitbucketBackend,ge as bitbucket,$ as bitbucketSetup,J as encodePath};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import{n as e,r as t,t as n}from"./store-BtVaZcVF.js";import{a as r,d as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,r as f,t as p,v as m}from"./setup-host-DQm73dc_.js";import{i as h,n as ee,r as g}from"./content-repository-setup-HEL-uoaX.js";import{n as _,o as v,r as y,s as b,t as x}from"./git-eGyMXUIu.js";import{t as S}from"./scheduled-builds-BPfDaBYt.js";async function C(e,t,n={}){let r=async r=>e.fetch(`${e.apiUrl}${t}`,{method:n.method??`GET`,headers:{authorization:`Bearer ${await e.token({refresh:r})}`,...n.body!==void 0&&{"content-type":`application/json`}},body:n.body===void 0?void 0:JSON.stringify(n.body),cache:`no-store`}),i=await r(!1);if(i.status===401&&e.canRefresh&&(i=await r(!0)),i.status===401)throw new _(`invalid`,`GitLab didn't accept the sign-in. It may have expired.`);if(!i.ok&&!n.allow?.includes(i.status)){let e=await i.json().catch(()=>({})),t=typeof e.message==`string`?e.message:JSON.stringify(e.message??e.error??``);throw new x(i.status,`GitLab answered ${i.status}: ${t||i.statusText}`)}return i}async function w(e,t,n){return await(await C(e,t,n)).json()}var T=30,E=40,te=`member:`,D=`invitation:`,ne=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,re=/^[\w][\w.-]*$/;function O(e){return e>=E?`owner`:e>=T?`editor`:`viewer`}function k(e){return e===`owner`?E:T}function A(e){throw e instanceof x&&(e.status===401||e.status===403)?new f(`not-allowed`,`Changing editors on GitLab needs the Maintainer role in the project.`):e}function j(e,t,n,r){let i=`/projects/${encodeURIComponent(t)}`,a=`${i}/protected_branches/${encodeURIComponent(n)}`;async function o(t){let n=[];for(let r=1;r<=10;r++){let i=await w(e,`${t}${t.includes(`?`)?`&`:`?`}per_page=100&page=${r}`);if(n.push(...i),i.length<100)break}return n}return{invitesByEmail:!0,async list(){let[t,n]=await Promise.all([o(`${i}/members/all`),o(`${i}/members`)]),s=new Set(n.map(e=>e.id)),c=t.find(e=>e.username.toLowerCase()===r.toLowerCase()),l=(c?.access_level??0)>=E,u=l?await o(`${i}/invitations`).catch(()=>[]):[],d=await C(e,a,{allow:[404]}),f=d.ok?(await d.json()).push_access_levels??[]:[],p=!d.ok||f.some(e=>e.access_level!==null&&e.access_level<=T);return{editors:[...t.map(e=>({id:`${te}${e.id}`,login:e.username,name:e.name,avatarUrl:e.avatar_url,role:O(e.access_level),...!s.has(e.id)&&{inherited:!0},...e.id===c?.id&&{self:!0}})),...u.map(e=>({id:`${D}${e.invite_email}`,email:e.invite_email,role:O(e.access_level),invited:!0}))],manage:l?`yes`:`no`,editorsCanPublish:p}},async invite(t,n){let r=t.trim().replace(/^@/,``);if(r.includes(`@`)){if(!ne.test(r))throw new f(`invalid`,`That isn't an email address.`);let t=await w(e,`${i}/invitations`,{method:`POST`,body:{email:r,access_level:k(n)}}).catch(A);if(t.status!==`success`){let e=typeof t.message==`string`?t.message:Object.values(t.message??{})[0];throw/already/i.test(e??``)?new f(`already`,`They've already been invited.`):new f(`invalid`,`GitLab didn't accept the invitation: ${e??t.status}`)}return}if(!re.test(r))throw new f(`invalid`,`That isn't a GitLab username or email address.`);let[a]=await w(e,`/users?${new URLSearchParams({username:r})}`);if(!a)throw new f(`not-found`,`There's no GitLab account named ${r}.`);try{await C(e,`${i}/members`,{method:`POST`,body:{user_id:a.id,access_level:k(n)}})}catch(e){if(e instanceof x&&e.status===409)throw new f(`already`,`${r} already edits the site.`);A(e)}},async setRole(t,n){await C(e,t.id.startsWith(D)?`${i}/invitations/${encodeURIComponent(t.id.slice(11))}`:`${i}/members/${t.id.slice(7)}`,{method:`PUT`,body:{access_level:k(n)}}).catch(A)},async remove(t){await C(e,t.id.startsWith(D)?`${i}/invitations/${encodeURIComponent(t.id.slice(11))}`:`${i}/members/${t.id.slice(7)}`,{method:`DELETE`}).catch(A)},async letEditorsPublish(){let t=t=>C(e,`${i}/protected_branches`,{method:`POST`,body:{name:n,push_access_level:t,merge_access_level:t,allow_force_push:!1}});await C(e,a,{method:`DELETE`,allow:[404]}).catch(A);try{await t(T)}catch(e){await t(E).catch(()=>void 0),A(e)}}}}var ie=`35.185.44.232`,ae=`2600:1901:0:7b8a::`;function M(e,{apex:t,www:n}){return t&&n?[e,`www.${e}`]:[e]}function N(e,t,n,r){let i=`${(e.split(`/`)[0]??``).toLowerCase()}.gitlab.io`,a=n.apex?[{type:`A`,name:t,value:ie,purpose:`site`},{type:`AAAA`,name:t,value:ae,purpose:`site`,optional:!0}]:[{type:`CNAME`,name:t,value:i,purpose:`site`}],o=n.apex&&n.www?[{type:`CNAME`,name:`www.${t}`,value:i,purpose:`www`,optional:!0}]:[],s=M(t,n).flatMap(e=>{let n=r[e];if(!n)return[];let i=n.startsWith(`gitlab-pages-verification-code=`)?n:`gitlab-pages-verification-code=${n}`;return[{type:`TXT`,name:`_gitlab-pages-verification-code.${e}`,value:i,purpose:`verification`,optional:e!==t}]});return[...a,...o,...s]}function oe(e,t){let n=`/projects/${encodeURIComponent(t)}/pages`,r=e=>`${n}/domains/${encodeURIComponent(e)}`;function i(e){throw e instanceof x&&(e.status===401||e.status===403)?new h(`not-allowed`,`Connecting a domain on GitLab needs the Maintainer role in the project.`):e}async function a(){let t=await C(e,n,{allow:[404]}).catch(i);return t.ok?await t.json():void 0}async function o(t){let n=await Promise.all(t.map(async t=>{let n=await C(e,r(t),{allow:[404]});return n.ok?[t,(await n.json()).verification_code??``]:[t,``]}));return Object.fromEntries(n)}async function s(t){let n=await w(e,r(t)).catch(i);if(n.verified)return n;let a=await C(e,`${r(t)}/verify`,{method:`PUT`,allow:[400,404,422]});return a.ok?await a.json():n}return{severalDomains:!0,async site(){let t=await a();if(!t)return;let r=(await w(e,`${n}/domains`).catch(()=>[])).map(e=>e.domain),i=(t.primary_domain&&r.includes(t.primary_domain)?t.primary_domain:void 0)??r.sort((e,t)=>e.length-t.length)[0];return{url:t.url,domain:i}},async connect(s,c){let l=await a();l&&l.is_unique_domain_enabled===!1&&await C(e,n,{method:`PATCH`,body:{pages_unique_domain_enabled:!0}}).catch(i);for(let t of M(s,c))try{await C(e,`${n}/domains`,{method:`POST`,body:{domain:t,auto_ssl_enabled:!0}})}catch(n){if(n instanceof x&&n.status===400){if(/taken/i.test(n.message)){if((await C(e,r(t),{allow:[404]})).ok)continue;throw new h(`taken`,`Another GitLab Pages site already uses this domain.`)}throw new h(`invalid`,`GitLab Pages doesn't accept this domain.`)}i(n)}return N(t,s,c,await o(M(s,c)))},async records(e,n){return N(t,e,n,await o(M(e,n)))},async status(t){let n=await s(t),i=await C(e,r(`www.${t}`),{allow:[404]});i.ok&&!(await i.json()).verified&&await s(`www.${t}`);let o=await a();return{verified:n.verified,certificate:n.certificate&&!n.certificate.expired?`ready`:`pending`,httpsOnly:o?.force_https===!0,primary:o?.primary_domain===void 0||o.primary_domain===t}},async secure(t,{primary:a=!0}={}){let o=await w(e,r(t)).catch(i);if(!o.verified||!o.certificate)throw new h(`not-ready`,`The domain's certificate isn't ready yet.`);if(!a){await C(e,n,{method:`PATCH`,body:{pages_https_only:!0}}).catch(i);return}try{await C(e,n,{method:`PATCH`,body:{pages_https_only:!0,pages_primary_domain:t}})}catch(t){t instanceof x&&t.status===400||i(t),await C(e,n,{method:`PATCH`,body:{pages_https_only:!0}}).catch(i)}},async disconnect(t){for(let n of[t,`www.${t}`])await C(e,r(n),{method:`DELETE`,allow:[404]}).catch(i)}}}var se=`Goodfellow: build the site for a scheduled change at `,ce=`GOODFELLOW_SCHEDULED_CHANGE`;function P(e){throw e instanceof x&&(e.status===401||e.status===403)?new S(`not-allowed`,`Adding pipeline schedules on GitLab needs the Developer role, with permission to merge to the main branch.`):e}function le(e){return`${e.getUTCMinutes()} ${e.getUTCHours()} ${e.getUTCDate()} ${e.getUTCMonth()+1} *`}function ue(e){return`${e.toISOString().slice(0,16)}Z`}function de(e,t,n,r,i=()=>new Date){let a=`/projects/${encodeURIComponent(t)}/pipeline_schedules`;return{async timing(){return await r()===void 0?`none`:`exact`},async sync(t){let r=i(),o=new Map;for(let e of[...t].filter(e=>e>r).sort((e,t)=>e.getTime()-t.getTime())){if(o.size>=50)break;o.set(ue(e),e)}let s=await w(e,`${a}?per_page=100`).catch(P),c=new Map;for(let e of s)e.description?.startsWith(`Goodfellow: build the site for a scheduled change at `)&&c.set(e.description.slice(53),e);for(let[t,n]of c)o.has(t)||await C(e,`${a}/${n.id}`,{method:`DELETE`,allow:[403,404]});for(let[t,r]of o){if(c.has(t))continue;let i=await w(e,a,{method:`POST`,body:{description:`${se}${t}`,ref:n,cron:le(r),cron_timezone:`UTC`,active:!0}}).catch(P);await C(e,`${a}/${i.id}/variables`,{method:`POST`,body:{key:ce,value:t,variable_type:`env_var`}}).catch(P)}}}}function fe(e,t,n,r,a={}){let o=`/projects/${encodeURIComponent(t)}`,s=a.wait??(e=>new Promise(t=>setTimeout(t,e))),u=async()=>(await r().catch(()=>void 0)??``).includes(`$GOODFELLOW_TASK_PLUGIN`);return{supported:u,secretsPlace:async()=>({kind:`gitlab`,url:`${e.apiUrl.replace(/\/api\/v4\/?$/,``)}/${t}/-/settings/ci_cd#js-cicd-variables-settings`}),async run(t){let r=l(t);if(r)throw new d(`failed`,r);if(!await u())throw new d(`missing`,`The site's setup files don't run plugins' tasks: .gitlab-ci.yml needs the plugin-task job.`);let f=(e,t)=>({key:e,variable_type:`env_var`,value:t}),p;try{p=await w(e,`${o}/pipeline`,{method:`POST`,body:{ref:n,variables:[f(`GOODFELLOW_TASK_REQUEST`,t.id),f(`GOODFELLOW_TASK_PLUGIN`,t.plugin),f(`GOODFELLOW_TASK_NAME`,t.task),f(`GOODFELLOW_TASK_INPUT`,t.input),f(`GOODFELLOW_TASK_KEY`,t.key)]}})}catch(e){throw e instanceof x&&(e.status===403||e.status===401)?new d(`not-allowed`,`Running plugins' tasks needs a sign-in that can publish to the site.`):e}let m=Date.now()+(a.timeoutMs??3e5);for(;;){let t=(await w(e,`${o}/pipelines/${p.id}/jobs?per_page=100`)).find(e=>e.name===c);if(t?.status===`success`){let n=await C(e,`${o}/jobs/${t.id}/artifacts/${i}`,{allow:[404]});if(n.ok)return await n.text();throw new d(`failed`,`The site's build service ran the task but left no answer.`)}if(t&&[`failed`,`canceled`,`skipped`].includes(t.status))throw new d(`failed`,`The site's build service couldn't run the task.`);if(Date.now()>=m)throw new d(`timeout`,`The site's build service didn't answer in time.`);await s(a.pollMs??4e3)}}}}var F=`.gitlab-ci.yml`,I=`17 4 * * *`;function L(e){throw e instanceof x&&(e.status===401||e.status===403)?new a(`not-allowed`,`Setting up updates on GitLab needs the Maintainer role in the project.`):e}function R(e,t,n,r,i=`pages`){let s=`/projects/${encodeURIComponent(t)}`;async function c(){return w(e,`${s}/pipeline_schedules`)}async function l(){return(await c()).find(e=>(e.ref===n||e.ref===`refs/heads/${n}`)&&!e.description?.startsWith(`Goodfellow: build the site for a scheduled change at `))}return{async setup(){if(!(await r(F))?.includes(`update --publish`))return`missing`;try{let[t,r]=await Promise.all([w(e,s),c()]),i=r.some(e=>(e.ref===n||e.ref===`refs/heads/${n}`)&&(e.active||!e.description?.startsWith(`Goodfellow: build the site for a scheduled change at `)));return t.ci_push_repository_for_job_token_allowed&&i?`ready`:`needs-setup`}catch(e){if(e instanceof x&&e.status===403)return`needs-setup`;throw e}},async enable(){await C(e,s,{method:`PUT`,body:{ci_push_repository_for_job_token_allowed:!0}}).catch(L),await l().catch(L)||await C(e,`${s}/pipeline_schedules`,{method:`POST`,body:{description:`Rebuild the site and install Goodfellow's fixes each night`,ref:n,cron:I,cron_timezone:`UTC`,active:!0}}).catch(L)},async lastRun(){let t=await w(e,`${s}/pipelines?${new URLSearchParams({ref:n,per_page:`20`})}`);for(let n of t){if(n.source!==`schedule`&&n.source!==`api`)continue;let t={date:n.created_at,detailsUrl:n.web_url};if([`created`,`pending`,`running`,`waiting_for_resource`,`preparing`].includes(n.status))return{state:`running`,...t};let r=(await w(e,`${s}/pipelines/${n.id}/jobs?per_page=100`)).find(e=>e.name===i||e.name===`update`);if(!r)continue;let a=await C(e,`${s}/jobs/${r.id}/trace`,{allow:[403,404]}),o=a.ok?m(await a.text()):void 0;if(o)return{state:o.state,result:o,...t}}},async start(t){await C(e,`${s}/pipeline`,{method:`POST`,body:{ref:n,variables:[{key:`GOODFELLOW_UPDATE`,variable_type:`env_var`,value:t}]}}).catch(L)},nightly:{async supported(){return(await r(F))?.includes(`nightly`)??!1},async get(){try{let t=await l();return t?t.active?(await w(e,`${s}/pipeline_schedules/${t.id}`)).variables?.find(e=>e.key===`GOODFELLOW_NIGHTLY`)?.value===`always`?`always`:`changed`:`off`:void 0}catch(e){if(e instanceof x&&e.status===403)return;throw e}},async set(t){let n=await l().catch(L);if(!n)throw new a(`missing`,`The site has no nightly schedule yet: turn on updates first.`);let r=`${s}/pipeline_schedules/${n.id}`;if(await C(e,r,{method:`PUT`,body:{active:t!==`off`}}).catch(L),t===`always`){let t={key:o,value:`always`};(await C(e,`${r}/variables/GOODFELLOW_NIGHTLY`,{method:`PUT`,body:t,allow:[404]}).catch(L)).status===404&&await C(e,`${r}/variables`,{method:`POST`,body:t}).catch(L)}else t===`changed`&&await C(e,`${r}/variables/${o}`,{method:`DELETE`,allow:[404]}).catch(L)}},async rebuild(){await C(e,`${s}/pipeline`,{method:`POST`,body:{ref:n,variables:[{key:`GOODFELLOW_REBUILD`,variable_type:`env_var`,value:`true`}]}}).catch(L)}}}function z(e){return e instanceof x&&(e.status===403||e.status===404)}function B(e){let{api:t,project:n}=e,r,i=()=>(r??=w(t,`/projects/${encodeURIComponent(n)}`).then(e=>e.default_branch),r.catch(()=>{r=void 0}),r),a=async()=>e.open(await i()),o=async e=>{let t=await a();return t.readAt(e,await t.revision())},s=async()=>R(t,n,await i(),o,`update`);return{code:{repo:n,webUrl:`${e.webUrl}/${n}`,read:o,history:async(e,t)=>(await a()).history(e,t),readAt:async(e,t)=>(await a()).readAt(e,t)},async setup(){try{return await(await s()).setup()}catch(e){if(z(e))return`no-access`;throw e}},async enable(){await(await s()).enable?.()},async lastRun(){try{return await(await s()).lastRun()}catch(e){if(z(e))return;throw e}},async start(e){await(await s()).start(e)},async rebuild(){await(await s()).rebuild?.()}}}var V=100,H=50,pe=RegExp(`\x1B\\[[\\d;]*[A-Za-z]`,`g`);async function me(e){let t=new TextEncoder().encode(`blob ${e.length}\0`),n=new Uint8Array(t.length+e.length);return n.set(t),n.set(e,t.length),[...new Uint8Array(await crypto.subtle.digest(`SHA-1`,n))].map(e=>e.toString(16).padStart(2,`0`)).join(``)}function U(e){return e.name!==`rebuild`&&e.name!==`update`&&e.name!==`lockfile`}function W(e,t){let n=`${t}/`;return[...e.keys()].filter(e=>e.startsWith(n)).sort()}var G=class i{user;pages;editors;updates;drafts;scheduledBuilds;tasks;contentOnly;options;api;project;branch;onSignOut;pinned;caches;trees;blobs;constructor(e){if(this.options=e,this.api=e.api,this.project=encodeURIComponent(e.project),this.branch=e.branch,this.user=e.user,this.onSignOut=e.onSignOut,this.pinned=e.revision,this.caches=e.caches??{trees:new Map,blobs:new Map},this.trees=this.caches.trees,this.blobs=this.caches.blobs,this.pages=oe(this.api,e.project),this.editors=j(this.api,e.project,this.branch,this.user.login),this.contentOnly=e.contentOnly===!0,!this.contentOnly)this.updates=R(this.api,e.project,this.branch,async e=>this.readAt(e,this.pinned??await this.revision()));else if(e.code){let t=e.code;this.updates=B({api:this.api,project:t.project,webUrl:t.webUrl,open:e=>new i({api:this.api,project:t.project,branch:e,user:this.user,onSignOut:()=>{}})})}this.drafts=r(this,this.draftHost()),this.scheduledBuilds=de(this.api,e.project,this.branch,async()=>this.readAt(`.gitlab-ci.yml`,this.pinned??await this.revision())),this.tasks=fe(this.api,e.project,this.branch,async()=>this.readAt(`.gitlab-ci.yml`,this.pinned??await this.revision()),e.tasks)}async repositoryVisibility(){let{visibility:e}=await w(this.api,`/projects/${this.project}`);return e===`public`||e===`internal`?e:`private`}draftHost(){let e=`/projects/${this.project}`,t=t=>w(this.api,`${e}/merge_requests?${new URLSearchParams({source_branch:t,state:`opened`})}`),n=async(t,n)=>{let r=[];for(let e of n){let[t]=await w(this.api,`/users?${new URLSearchParams({username:e})}`).catch(()=>[]);t&&r.push(t.id)}for(let n of r.length>1?[r,r.slice(0,1)]:[r])if(n.length===0||(await C(this.api,`${e}/merge_requests/${t}`,{method:`PUT`,body:{reviewer_ids:n},allow:[400,403,404,422]})).ok)return};return{liveBranch:this.branch,branchStore:e=>new i({...this.options,branch:e,caches:this.caches}),createBranch:async(e,t)=>{if((await C(this.api,this.repo(`/branches?${new URLSearchParams({branch:e,ref:t})}`),{method:`POST`,allow:[400]})).status===400)throw new s(`exists`,`There's already a draft called ${e}.`)},deleteBranch:async e=>{await C(this.api,this.repo(`/branches/${encodeURIComponent(e)}`),{method:`DELETE`,allow:[404]})},mergeBase:async e=>{let t=new URLSearchParams;t.append(`refs[]`,this.branch),t.append(`refs[]`,e);let n=await C(this.api,this.repo(`/merge_base?${t}`),{allow:[400,404]});if(!n.ok)throw new s(`not-found`,`There's no draft ${e}.`);return(await n.json()).id},listBranches:async e=>{let t=new URLSearchParams({search:`^${e}`,per_page:`100`});return(await w(this.api,this.repo(`/branches?${t}`))).map(e=>e.name).filter(t=>t.startsWith(e))},openReview:async({branch:r,title:i,description:a,reviewers:o=[]})=>{let c=await C(this.api,`${e}/merge_requests`,{method:`POST`,body:{source_branch:r,target_branch:this.branch,title:i,description:a,remove_source_branch:!0},allow:[403,404,409]}),l;if(c.ok)l=await c.json();else if(c.status!==409)throw new s(`no-reviews`,`This sign-in can't open merge requests on the site's project.`);else if([l]=await t(r),!l)throw new x(409,`GitLab couldn't open the merge request.`);return await n(l.iid,o),{url:l.web_url}},listReviews:async t=>{let n=new URLSearchParams({state:`opened`,per_page:`100`});return(await w(this.api,`${e}/merge_requests?${n}`)).filter(e=>e.source_branch.startsWith(t)).map(e=>({branch:e.source_branch,url:e.web_url,title:e.title}))},closeReview:async n=>{for(let r of await t(n))await C(this.api,`${e}/merge_requests/${r.iid}`,{method:`PUT`,body:{state_event:`close`},allow:[403,404]})}}}repo(e){return`/projects/${this.project}/repository${e}`}async revision(){return this.pinned=await this.head(),this.pinned}async head(){return(await w(this.api,this.repo(`/branches/${encodeURIComponent(this.branch)}`))).commit.id}async listFolder(e,t){let n=[];for(let r=1;;r++){let i=new URLSearchParams({ref:e,path:t,recursive:`true`,per_page:String(V),page:String(r)}),a=await C(this.api,this.repo(`/tree?${i}`),{allow:[404]});if(a.status===404)return n;let o=await a.json();for(let e of o)e.type===`blob`&&n.push([e.path,e.id]);if(o.length<V)return n}}tree(t){let n=this.trees.get(t);return n||(n=Promise.all(e.map(e=>this.listFolder(t,e))).then(e=>new Map(e.flat())),n.catch(()=>this.trees.delete(t)),this.trees.set(t,n)),n}async currentTree(){return this.tree(this.pinned??await this.revision())}async read(e){return this.readFrom(await this.currentTree(),e)}readFrom(e,t){let n=e.get(t);if(!n)return Promise.resolve(void 0);let r=this.blobs.get(n);return r||(r=C(this.api,this.repo(`/blobs/${n}/raw`)).then(e=>e.text()),r.catch(()=>this.blobs.delete(n)),this.blobs.set(n,r)),r}async readFiles(e){let t=this.pinned??await this.revision();return this.readFilesFrom(t,await this.tree(t),e)}async readFilesFrom(e,t,n){let r=n.filter(e=>t.has(e)),i=r.filter(e=>!this.blobs.has(t.get(e)??``));for(let n=0;n<i.length;n+=H){let r=i.slice(n,n+H),a=await w(this.api,`/../graphql`,{method:`POST`,body:{query:`query ($project: ID!, $ref: String!, $paths: [String!]!) {
|
|
2
|
-
project(fullPath: $project) { repository { blobs(ref: $ref, paths: $paths) { nodes { path rawTextBlob } } } }
|
|
3
|
-
}`,variables:{project:decodeURIComponent(this.project),ref:e,paths:r}}});for(let e of a.data?.project?.repository?.blobs?.nodes??[]){let n=t.get(e.path);n&&typeof e.rawTextBlob==`string`&&this.blobs.set(n,Promise.resolve(e.rawTextBlob))}}let a=new Map;for(let e of r){let n=await this.readFrom(t,e);n!==void 0&&a.set(e,n)}return a}async readBytes(e){return this.bytesFrom(await this.currentTree(),e)}async bytesFrom(e,t){let n=e.get(t);if(!n)return;let r=await C(this.api,this.repo(`/blobs/${n}/raw`));return new Uint8Array(await r.arrayBuffer())}async list(e){return W(await this.currentTree(),e)}filesAt(e){return{read:async t=>this.readFrom(await this.tree(e),t),readFiles:async t=>this.readFilesFrom(e,await this.tree(e),t),readBytes:async t=>this.bytesFrom(await this.tree(e),t),list:async t=>W(await this.tree(e),t)}}async fileSizes(e){let t=await this.list(e),n=this.pinned??await this.revision(),r=new Map;for(let e=0;e<t.length;e+=H){let i=await w(this.api,`/../graphql`,{method:`POST`,body:{query:`query ($project: ID!, $ref: String!, $paths: [String!]!) {
|
|
4
|
-
project(fullPath: $project) { repository { blobs(ref: $ref, paths: $paths) { nodes { path size } } } }
|
|
5
|
-
}`,variables:{project:decodeURIComponent(this.project),ref:n,paths:t.slice(e,e+H)}}});for(let e of i.data?.project?.repository?.blobs?.nodes??[]){let t=Number(e.size);Number.isFinite(t)&&r.set(e.path,t)}}return r}async lastCommitFor(e,t){return(await w(this.api,this.repo(`/files/${encodeURIComponent(e)}?ref=${t}`))).last_commit_id}async existsAt(t,n,r){return e.some(e=>n.startsWith(`${e}/`))?t.has(n):this.lastCommitFor(n,r).then(()=>!0,e=>{if(e instanceof x&&e.status===404)return!1;throw e})}async write(e,{message:r,expectedRevision:i}){if(this.contentOnly&&t(e),await this.revision()!==i)throw new n;let a=await this.tree(i),o=(await Promise.all(e.map(async e=>{let t=await this.existsAt(a,e.path,i);if(`delete`in e)return t?{action:`delete`,file_path:e.path,last_commit_id:await this.lastCommitFor(e.path,i)}:void 0;let n=`bytes`in e?{content:v(e.bytes),encoding:`base64`}:{content:e.content};return t?{action:`update`,file_path:e.path,...n,last_commit_id:await this.lastCommitFor(e.path,i)}:{action:`create`,file_path:e.path,...n}}))).filter(e=>e!==void 0);if(o.length===0)return{revision:i};try{let t=await w(this.api,this.repo(`/commits`),{method:`POST`,body:{branch:this.branch,commit_message:r,actions:o,...this.options.author&&{author_name:this.options.author.name,author_email:this.options.author.email}}});return this.pinned=t.id,t.parent_ids?.length===1&&t.parent_ids[0]===i&&await this.carryTree(a,t.id,e).catch(()=>{}),{revision:t.id}}catch(e){throw e instanceof x?e.status===403?new _(`cant-publish`,`This GitLab account can't publish to the site.`):e.status===400&&/already exists|changed since/i.test(e.message)||await this.revision()!==i?new n:e:e}}async carryTree(t,n,r){if(this.trees.has(n)||!globalThis.crypto?.subtle)return;let i=new Map(t);for(let t of r){if(!e.some(e=>t.path.startsWith(`${e}/`)))continue;if(`delete`in t){i.delete(t.path);continue}let n=await me(`bytes`in t?t.bytes:new TextEncoder().encode(t.content));i.set(t.path,n),`content`in t&&!this.blobs.has(n)&&this.blobs.set(n,Promise.resolve(t.content))}this.trees.set(n,Promise.resolve(i))}async history(e,{page:t=1,perPage:n=20}={}){let r=new URLSearchParams({ref_name:this.pinned??await this.revision(),path:e,per_page:String(n),page:String(t)});return(await w(this.api,this.repo(`/commits?${r}`))).map(e=>({revision:e.id,date:e.authored_date??e.committed_date??``,author:e.author_name||void 0,message:e.title}))}async readAt(e,t){let n=await C(this.api,this.repo(`/files/${encodeURIComponent(e)}/raw?${new URLSearchParams({ref:t})}`),{allow:[404]});return n.ok?n.text():void 0}async changedPaths(e,t){let n=await w(this.api,this.repo(`/compare?${new URLSearchParams({from:e,to:t,straight:`true`})}`));return[...new Set((n.diffs??[]).flatMap(e=>[e.old_path,e.new_path]))]}async deployStatus(e){try{let t=await this.statuses(e),n=t.filter(U);if(t.length>0&&n.length===0)return{state:`unknown`};if(n.length===0){if((await w(this.api,`/projects/${this.project}/pipelines?per_page=1`)).length>0)return{state:`building`};let{parent_ids:t=[]}=await w(this.api,this.repo(`/commits/${e}`));return{state:(t[0]?(await this.statuses(t[0])).filter(U):[]).length>0?`building`:`unknown`}}let r=n.find(e=>e.status===`failed`)??n.find(e=>e.status===`canceled`);if(r?.status===`canceled`){let t=await this.head();if(t!==e)return this.deployStatus(t)}if(r){let t=await this.jobProblem(e).catch(()=>void 0);return{state:`failed`,detailsUrl:r.target_url??void 0,...t&&{problem:t}}}return n.every(e=>e.status===`success`||e.status===`skipped`)?{state:`live`,detailsUrl:n[0]?.target_url??void 0}:{state:`building`,detailsUrl:n[0]?.target_url??void 0}}catch(e){if(e instanceof x)return{state:`unknown`};throw e}}statuses(e){return w(this.api,this.repo(`/commits/${e}/statuses`))}async jobProblem(e){let[t]=await w(this.api,`/projects/${this.project}/pipelines?${new URLSearchParams({sha:e,per_page:`1`})}`);if(!t)return;let n=(await w(this.api,`/projects/${this.project}/pipelines/${t.id}/jobs?per_page=100`)).find(e=>e.status===`failed`);if(!n)return;let r=n.failure_reason??``,i=`${n.name}: ${r}`;if(r===`ci_quota_exceeded`)return{step:`not-started`,detail:i};if(/runner_system|stuck_or_timeout|scheduler|api_failure|data_integrity|job_execution_timeout/.test(r))return{step:`host`,detail:i};if(n.name===`pages:deploy`)return{step:`deploy`,detail:i};let a=await C(this.api,`/projects/${this.project}/jobs/${n.id}/trace`,{allow:[403,404]}),o=a.ok?await a.text():``,s=g(o),c=o.split(`
|
|
6
|
-
`).map(e=>e.replace(pe,``).replace(/^.*\r/,``)).filter(e=>e.startsWith(`$ `)).at(-1);return{step:s?`build`:(c?ee(c):void 0)??`build`,detail:i,...s&&{cause:s}}}signOut(){this.onSignOut()}};function K(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function q(e=32){return K(crypto.getRandomValues(new Uint8Array(e)))}async function J(e){let t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return K(new Uint8Array(t))}function Y(e,t,n=Date.now()){return{type:`oauth`,access:e.access_token,refresh:e.refresh_token,expiresAt:n+(e.expires_in??7200)*1e3,verifier:t}}function X(e){let t=new URL(e);return`${t.origin}${t.pathname.replace(/\/?$/,`/`)}`}var Z=`main`;function he(){return{href:()=>window.location.href,assign:e=>window.location.assign(e),replace:e=>window.history.replaceState(window.history.state,``,e)}}function Q(e={}){let t=(e.url??`https://gitlab.com`).replace(/\/$/,``),n=`${t}/api/v4`,r=e.fetch??((e,t)=>globalThis.fetch(e,t)),i=y(`goodfellow:gitlab-setup:pending`,e.storage),a=()=>e.location??he();async function o(e){let n=await r(`${t}/oauth/token`,{method:`POST`,headers:{"content-type":`application/x-www-form-urlencoded`},body:new URLSearchParams(e)});if(!n.ok)throw new _(`invalid`,`GitLab didn't accept the sign-in (${n.status}).`);return await n.json()}async function s(t){let i=t,s={apiUrl:n,token:async({refresh:t}={})=>{if(i.type===`token`)return i.token;if(t||i.expiresAt-6e4<Date.now()){let{verifier:t}=i;i=Y(await o({client_id:e.clientId??``,refresh_token:i.refresh,grant_type:`refresh_token`,redirect_uri:X(a().href()),code_verifier:t}),t)}return i.access},canRefresh:i.type===`oauth`,fetch:r},c=await w(s,`/user`);async function l(e,t){return(await C(s,`/projects/${encodeURIComponent(`${e.path}/${t}`)}`,{allow:[404]})).status===404}async function u(e){let t=e=>`/projects/${encodeURIComponent(e)}`;try{let n=new Map;for(let r of[`code`,`content`])n.set(r,(await w(s,t(e[r]))).id);for(let{reader:r,read:i}of e.links.reads)await C(s,`${t(e[i])}/job_token_scope/allowlist`,{method:`POST`,body:{target_project_id:n.get(r)}});e.links.updates&&await C(s,t(e[e.links.updates]),{method:`PUT`,body:{ci_push_repository_for_job_token_allowed:!0}});for(let n of e.links.nightly)await C(s,`${t(e[n])}/pipeline_schedules`,{method:`POST`,body:{description:n===e.links.updates?`Rebuild the site and install Goodfellow's fixes each night`:`Rebuild the site each night`,ref:Z,cron:I,cron_timezone:`UTC`,active:!0}});return!0}catch(e){if(e instanceof x&&[400,403,404].includes(e.status))return!1;throw e}}return{user:{login:c.username,name:c.name,avatarUrl:c.avatar_url},async owners(){let e=(await w(s,`/namespaces?per_page=100`)).map(e=>({path:e.full_path,name:e.kind===`user`?c.name??e.name:e.name,kind:e.kind===`user`?`personal`:`organization`,id:e.id}));return[...e.filter(e=>e.kind===`personal`),...e.filter(e=>e.kind!==`personal`)]},isAvailable:l,async createSite(e,t){if(t?.(`repository`),!await l(e.owner,e.name))throw new p(`name-taken`,`There's already a project called ${e.owner.path}/${e.name}.`);let n;try{n=await w(s,`/projects`,{method:`POST`,body:{name:e.name,path:e.name,namespace_id:e.owner.id,visibility:e.private?`private`:`public`,description:e.description,...e.pages&&{pages_access_level:e.private?`public`:`enabled`}}})}catch(t){throw t instanceof x&&t.status===400?new p(`name-invalid`,`GitLab can't use "${e.name}" as a project name.`):t instanceof x&&(t.status===403||t.status===404)?new p(`not-allowed`,`This sign-in can't create projects in ${e.owner.path}.`):t}let r=[];e.link&&(t?.(`connect`),await u(e.link)||r.push(`connect-unavailable`));let i;if(e.pages&&e.domain){t?.(`pages`);try{await C(s,`/projects/${n.id}/pages/domains`,{method:`POST`,body:{domain:e.domain,auto_ssl_enabled:!0}}),i=`https://${e.domain}/`}catch(e){if(!(e instanceof x)||![400,403,404,409,422].includes(e.status))throw e;r.push(`domain-unavailable`)}}return t?.(`files`),await C(s,`/projects/${n.id}/repository/commits`,{method:`POST`,body:{branch:Z,commit_message:e.message,actions:e.files.flatMap(e=>`delete`in e?[]:`content`in e?[{action:`create`,file_path:e.path,content:e.content}]:[{action:`create`,file_path:e.path,content:v(e.bytes),encoding:`base64`}])}}),{repo:n.path_with_namespace,webUrl:n.web_url,...i&&{siteUrl:i},buildsUrl:`${n.web_url}/-/pipelines`,pagesUrl:e.pages?`${n.web_url}/pages`:void 0,warnings:r}}}}return{name:`GitLab`,canRedirect:!!e.clientId,tokenLinks:[{url:`${t}/-/user_settings/personal_access_tokens?${new URLSearchParams({name:`Goodfellow site setup`,scopes:`api`})}`,label:`signIn.token.create`}],async restore(){let t=new URL(a().href()),n=t.searchParams.get(`code`),r=t.searchParams.get(`error`);if(!n&&!r)return null;let c=i.load();if(!c)return null;i.clear();let l=JSON.parse(c),u=t.searchParams.get(`state`);for(let e of[`code`,`state`,`error`,`error_description`])t.searchParams.delete(e);if(a().replace(t.toString()),r||!n||u!==l.state)throw new _(`redirect-failed`,`Signing in with GitLab was cancelled or didn't finish.`);return s(Y(await o({client_id:e.clientId??``,code:n,grant_type:`authorization_code`,redirect_uri:X(t.toString()),code_verifier:l.verifier}),l.verifier))},async signInWithToken(e){let t=e.trim();if(!t)throw new _(`invalid`,`Paste a token to sign in.`);return s({type:`token`,token:t})},async startRedirect(){if(!e.clientId)throw Error(`gitlabSetup({ clientId }) is needed to sign in with GitLab.`);let n={state:q(16),verifier:q(48)};i.save(JSON.stringify(n),!1);let r=new URLSearchParams({client_id:e.clientId,redirect_uri:X(a().href()),response_type:`code`,state:n.state,scope:`api`,code_challenge:await J(n.verifier),code_challenge_method:`S256`});a().assign(`${t}/oauth/authorize?${r}`)}}}var ge=30;function $(){return{href:()=>window.location.href,assign:e=>window.location.assign(e),replace:e=>window.history.replaceState(window.history.state,``,e)}}function _e(e){let t=(e.url??`https://gitlab.com`).replace(/\/$/,``),n=`${t}/api/v4`,r=u(e.fetch??((e,t)=>globalThis.fetch(e,t)),{host:`GitLab`}),i=y(`goodfellow:gitlab:${t}:${e.project}`,e.storage),a=y(`goodfellow:gitlab:pending:${e.project}`,e.storage),o=()=>e.location??$();async function s(e){let n=await r(`${t}/oauth/token`,{method:`POST`,headers:{"content-type":`application/x-www-form-urlencoded`},body:new URLSearchParams(e)});if(!n.ok)throw new _(`invalid`,`GitLab didn't accept the sign-in (${n.status}).`);return await n.json()}async function c(a,c){let l=a,u={apiUrl:n,token:async({refresh:t}={})=>{if(l.type===`token`)return l.token;if(t||l.expiresAt-6e4<Date.now()){let{verifier:t}=l;l=Y(await s({client_id:e.clientId??``,refresh_token:l.refresh,grant_type:`refresh_token`,redirect_uri:X(o().href()),code_verifier:t}),t),i.save(JSON.stringify(l),c)}return l.access},canRefresh:l.type===`oauth`,fetch:r},d=await w(u,`/user`),f;try{f=await w(u,`/projects/${encodeURIComponent(e.project)}`)}catch(t){throw t instanceof x&&(t.status===404||t.status===403)?new _(`no-access`,`The GitLab account ${d.username} can't see ${e.project}.`):t}if(Math.max(f.permissions?.project_access?.access_level??0,f.permissions?.group_access?.access_level??0)<ge)throw new _(`cant-publish`,`The GitLab account ${d.username} can see ${e.project} but can't publish to it.`);return i.save(JSON.stringify(l),c),new G({api:u,project:e.project,branch:e.branch??f.default_branch,...e.contentOnly&&{contentOnly:!0},...e.contentOnly&&e.code&&{code:{project:e.code,webUrl:t}},user:{login:d.username,name:d.name,avatarUrl:d.avatar_url},onSignOut:()=>i.clear()})}async function l(){let t=new URL(o().href()),n=t.searchParams.get(`code`),r=t.searchParams.get(`state`),i=t.searchParams.get(`error`);if(!n&&!i)return null;let l=a.load();if(!l)return null;a.clear();let u=JSON.parse(l);for(let e of[`code`,`state`,`error`,`error_description`])t.searchParams.delete(e);if(t.hash=u.hash,o().replace(t.toString()),i||!n||r!==u.state)throw new _(`redirect-failed`,`Signing in with GitLab was cancelled or didn't finish.`);return c(Y(await s({client_id:e.clientId??``,code:n,grant_type:`authorization_code`,redirect_uri:X(t.toString()),code_verifier:u.verifier}),u.verifier),u.remember)}function d({token:t}){let i={apiUrl:n,token:async()=>typeof t==`string`?t:t(),canRefresh:!1,fetch:r},a,o=()=>(a??=e.branch?Promise.resolve(e.branch):w(i,`/projects/${encodeURIComponent(e.project)}`).then(e=>e.default_branch),a.catch(()=>{a=void 0}),a),s=async(t,n)=>new G({api:i,project:e.project,branch:await o(),...e.contentOnly&&{contentOnly:!0},user:{login:n?.name??e.project,...n&&{name:n.name}},onSignOut:()=>{},...t&&{revision:t},...n&&{author:n}});return{...e.contentOnly&&{contentOnly:!0},async revision(){return(await s()).revision()},at:s}}return{name:`GitLab`,source:b(`@goodfellow-cms/gitlab`,`gitlab`,e,[`fetch`,`storage`,`location`]),canRedirect:!!e.clientId,setup:()=>Q({...e.url&&{url:e.url},...e.fetch&&{fetch:e.fetch},...e.storage&&{storage:e.storage},...e.location&&{location:e.location}}),redirectAddressesListed:!!e.clientId,tokenLinks:[{url:`${t}/-/user_settings/personal_access_tokens?${new URLSearchParams({name:`Goodfellow admin`,scopes:`api`})}`,label:`signIn.token.create`}],async restore(){let e=await l();if(e)return e;let t=i.load();if(!t)return null;try{return await c(JSON.parse(t),i.remembered())}catch(e){throw e instanceof _&&i.clear(),e}},async signInWithToken(e,t){let n=e.trim();if(!n)throw new _(`invalid`,`Paste a token to sign in.`);return c({type:`token`,token:n},t)},async startRedirect(n){if(!e.clientId)throw Error(`gitlab({ clientId }) is needed to sign in with GitLab.`);let r=q(48),i=q(16),s=new URL(o().href()),c={state:i,verifier:r,remember:n,hash:s.hash};a.save(JSON.stringify(c),!1);let l=new URLSearchParams({client_id:e.clientId,redirect_uri:X(s.toString()),response_type:`code`,state:i,scope:`api`,code_challenge:await J(r),code_challenge_method:`S256`});o().assign(`${t}/oauth/authorize?${l}`)},server:d}}export{G as GitLabBackend,_e as gitlab,N as gitlabPagesRecords,Q as gitlabSetup,X as redirectUri};
|