@goodfellow-cms/broker 0.5.0 → 0.7.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.
@@ -0,0 +1 @@
1
+ var e=class extends Error{problem;name=`ScheduledBuildsError`;constructor(e,t){super(t),this.problem=e}};export{e as t};
@@ -0,0 +1,2 @@
1
+ import{a as e}from"./store-BtVaZcVF.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
+ `);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};
@@ -0,0 +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||(await e.changedPaths(n.expectedRevision,o)).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,15 +1,18 @@
1
1
  {
2
2
  "files": [
3
3
  "_headers",
4
+ "assets/content-repository-setup-HEL-uoaX.js",
4
5
  "assets/deploy-keys-DAj2oX-N-DRd_HmOG.js",
5
- "assets/dist-C20K9oCc.js",
6
- "assets/dist-cedgnWG_.js",
6
+ "assets/dist-DAzQ31j6.js",
7
+ "assets/dist-Dkr_h4iS.js",
8
+ "assets/dist-Dob4V5zY.js",
7
9
  "assets/git-eGyMXUIu.js",
10
+ "assets/index-BL-VYiot.js",
8
11
  "assets/index-BQoQNxGe.css",
9
- "assets/index-Cb7Ya0Pj.js",
10
12
  "assets/preload-helper-khBccGFq.js",
11
- "assets/setup-host-w4Qxug91.js",
12
- "assets/store-5raQS3us.js",
13
+ "assets/scheduled-builds-BPfDaBYt.js",
14
+ "assets/setup-host-DQm73dc_.js",
15
+ "assets/store-BtVaZcVF.js",
13
16
  "broker.example.json",
14
17
  "index.html",
15
18
  "vercel.json"
package/site/index.html CHANGED
@@ -9,8 +9,8 @@
9
9
  />
10
10
  <meta name="referrer" content="no-referrer" />
11
11
  <title>Sign in</title>
12
- <script type="module" crossorigin src="./assets/index-Cb7Ya0Pj.js"></script>
13
- <link rel="modulepreload" crossorigin href="./assets/store-5raQS3us.js">
12
+ <script type="module" crossorigin src="./assets/index-BL-VYiot.js"></script>
13
+ <link rel="modulepreload" crossorigin href="./assets/store-BtVaZcVF.js">
14
14
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-khBccGFq.js">
15
15
  <link rel="stylesheet" crossorigin href="./assets/index-BQoQNxGe.css">
16
16
  </head>
@@ -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-5raQS3us.js";import{a as n,d as r,f as i,l as a,m as o,n as s,o as c,p as l,r as u,s as d,t as f,u as p}from"./setup-host-w4Qxug91.js";import{a as m,i as h,n as g,o as _,r as v,s as ee,t as y}from"./git-eGyMXUIu.js";import{t as b}from"./preload-helper-khBccGFq.js";async function x({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 g(`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 y(o.status,`GitHub answered ${o.status}: ${e.message??o.statusText}`)}return o}async function S(e,t,n){return await(await x(e,t,n)).json()}function C(e){return e.split(`/`).map(e=>encodeURIComponent(e)).join(`/`)}var w=/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i,T=`invitation:`;function E(e){return e?.admin?`owner`:e?.maintain||e?.push?`editor`:`viewer`}function D(e){return e===`admin`?`owner`:e===`write`||e===`maintain`?`editor`:`viewer`}function O(e){return e instanceof y&&(e.status===403||e.status===404)}function te(e,t,n,i){let a=`/repos/${n}`;function o(){let e=t();if(!e)throw new r(`not-allowed`,`Changing editors on GitHub needs an owner token.`);return e}async function s(e){try{await e(o())}catch(e){throw O(e)?new r(`not-allowed`,`This token can't change the site's editors.`):e}}async function c(e){let t=[];for(let n=1;n<=10;n++){let r=await S(e,`${a}/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,r=await c(n),o;try{o=await S(n,`${a}/invitations?per_page=100`)}catch(e){if(!O(e))throw e}let s=[...r.map(e=>({id:e.login,login:e.login,avatarUrl:e.avatar_url,role:E(e.permissions),...e.login.toLowerCase()===i.toLowerCase()&&{self:!0}})),...(o??[]).flatMap(e=>e.invitee?[{id:`${T}${e.id}`,login:e.invitee.login,avatarUrl:e.invitee.avatar_url,role:D(e.permissions),invited:!0}]:[])],l=s.some(e=>e.self&&e.role===`owner`);return{editors:s,manage:o?`yes`:l?`token`:`no`,editorsCanPublish:!0}},async invite(e,t){let n=e.trim().replace(/^@/,``);if(!w.test(n))throw new r(`invalid`,`That isn't a GitHub username.`);let i=o();try{await x(i,`${a}/collaborators/${encodeURIComponent(n)}`,{method:`PUT`,body:{permission:t===`owner`?`admin`:`push`}})}catch(e){throw e instanceof y&&e.status===404&&(await x(i,`/users/${encodeURIComponent(n)}`,{allow:[404]})).status===404?new r(`not-found`,`There's no GitHub account named ${n}.`):O(e)?new r(`not-allowed`,`This token can't change the site's editors.`):e instanceof y&&e.status===422?new r(`invalid`,`GitHub didn't accept the invitation: ${e.message}`):e}},async setRole(e,t){await s(async n=>{e.id.startsWith(T)?await x(n,`${a}/invitations/${e.id.slice(11)}`,{method:`PATCH`,body:{permissions:t===`owner`?`admin`:`write`}}):await x(n,`${a}/collaborators/${encodeURIComponent(e.id)}`,{method:`PUT`,body:{permission:t===`owner`?`admin`:`push`}})})},async remove(e){await s(t=>x(t,e.id.startsWith(T)?`${a}/invitations/${e.id.slice(11)}`:`${a}/collaborators/${encodeURIComponent(e.id)}`,{method:`DELETE`}))}}}function ne(e,t,n,i){let a,o,s,c;return{access:{tokenLink:n,get active(){return a!==void 0},get problem(){return c},...i&&{async startRedirect(e){c=void 0,await i(e)}},async applyToken(n){let i={...e,token:n.trim()};try{if(!(await S(i,`/repos/${t}`)).permissions?.admin)throw new r(`not-allowed`,`This token's account isn't an owner of the site.`);await S(i,`/repos/${t}/invitations?per_page=1`)}catch(e){throw e instanceof r?e:e instanceof g||O(e)?new r(`not-allowed`,`This token can't change the site's editors.`):e}a=i,o=i,c=void 0},forget(){a=void 0,o=void 0,s?.(),s=void 0}},api:()=>a,codeApi:()=>o,useSignIn(t,n,r){a={...e,token:t},o=r?{...e,token:r}:void 0,s=n,c=void 0},failed(e){c=e}}}var re=[`185.199.108.153`,`185.199.109.153`,`185.199.110.153`,`185.199.111.153`],ie=[`2606:50c0:8000::153`,`2606:50c0:8001::153`,`2606:50c0:8002::153`,`2606:50c0:8003::153`],k=new Set([`approved`,`issued`,`uploaded`]),A=new Set([`errored`,`bad_authz`,`authorization_revoked`]);function j(e,t,{apex:n,www:r}){let i=`${(e.split(`/`)[0]??``).toLowerCase()}.github.io`;return n?[...re.map(e=>({type:`A`,name:t,value:e,purpose:`site`})),...ie.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 ae(e,t){let n=`/repos/${t}/pages`;async function r(){let t=await x(e(),n,{allow:[404]});return t.status===404?void 0:await t.json()}async function i(t){try{await x(e(),n,{method:`PUT`,body:t})}catch(e){throw e instanceof y&&(e.status===403||e.status===404)?new o(`not-allowed`,`This sign-in can't change the site's GitHub Pages settings.`):e instanceof y&&(e.status===400||e.status===422)?/taken|already/i.test(e.message)?new o(`taken`,`Another GitHub Pages site already uses this domain.`):`https_enforced`in t?new o(`not-ready`,`The domain's certificate isn't ready yet.`):new o(`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}),j(t,e,n)},async records(e,n){return j(t,e,n)},async status(t){let r=await S(e(),n),i=r.https_certificate?.state??``;return{verified:!0,certificate:k.has(i)?`ready`:A.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 oe=`.github/workflows/scheduled.yml`,se=[`.github/workflows/deploy.yml`,`.github/workflows/rebuild.yml`];function ce(e){return{async timing(){let[t,...n]=await Promise.all([oe,...se].map(e));return t&&/\bdue\b/.test(t)&&/\bschedule:/.test(t)?`hourly`:n.some(e=>e&&/\bschedule:/.test(e))?`nightly`:`none`}}}var le=`deploy.yml`,ue=`update.yml`,de=`publish-update`;function M(e,t,n,r,i,a=le){let o=`/repos/${n}/actions/workflows/${a}`,s=`.github/workflows/${a}`;return{async setup(){let e=await i.read(s);return e&&/update --(publish|commit)\b/.test(e)?`ready`:`missing`},async lastRun(){let t=await x(e,`${o}/runs?branch=${encodeURIComponent(r)}&per_page=20`,{allow:[403,404]});if(!t.ok)return;let{workflow_runs:a=[]}=await t.json();for(let t of a.filter(e=>[`schedule`,`workflow_dispatch`].includes(e.event))){let r={date:t.created_at,detailsUrl:t.html_url};if(t.status!==`completed`)return{state:`running`,...r};let{jobs:a=[]}=await S(e,`/repos/${n}/actions/runs/${t.id}/jobs`),o=a.find(e=>e.name===`update`);if(!o||o.conclusion===`skipped`)continue;if(o.conclusion!==`success`)return{state:`failed`,...r};let s=a.find(e=>e.name===de);if(s&&s.conclusion!==`success`&&s.conclusion!==`skipped`)return{state:`failed`,...r};let c=p(await i.readAt(`package.json`,t.head_sha)??``),l=p(await i.read(`package.json`)??``);if(!c||!l||c===l)return{state:`up-to-date`,...r};let u=d(l,c)<0;return{state:`updated`,...r,result:{state:`updated`,from:c,to:l,...u&&{rollback:u}}}}},nightly:fe(e,t,n,()=>i.read(s)),async rebuild(){await l({})},async start(e){await l({update:e})}};async function l(n){try{await x(t()??e,`${o}/dispatches`,{method:`POST`,body:{ref:r,inputs:n}})}catch(e){throw e instanceof y&&(e.status===403||e.status===401)?new c(`not-allowed`,`Running the site's build needs a token that can run its workflows.`):e instanceof y&&(e.status===404||e.status===422)?new c(`missing`,`The site's GitHub Pages workflow doesn't update Goodfellow.`):e}}}function fe(e,t,r,i){let o=`/repos/${r}/actions/variables`,s=e=>{throw e instanceof y&&(e.status===401||e.status===403)?new c(`not-allowed`,`Changing when the site rebuilds needs GitHub's Variables permission.`):e};return{async supported(){return(await i())?.includes(`GOODFELLOW_NIGHTLY`)??!1},async get(){let r=await x(t()??e,`${o}/${n}`,{allow:[403,404]});if(r.status===404)return`changed`;if(r.ok)return a((await r.json()).value)},async set(r){let i=t()??e;if(r===`changed`){await x(i,`${o}/${n}`,{method:`DELETE`,allow:[404]}).catch(s);return}let a={name:n,value:r};(await x(i,`${o}/GOODFELLOW_NIGHTLY`,{method:`PATCH`,body:a,allow:[404]}).catch(s)).status===404&&await x(i,o,{method:`POST`,body:a}).catch(s)}}}function N(e){return e instanceof g&&e.problem===`no-access`||e instanceof y&&(e.status===403||e.status===404)}function pe(e){let{read:t}=e,n=C(e.repo),r,i=e=>(r??=S(e,`/repos/${n}`).then(e=>e.default_branch),r.catch(()=>{r=void 0}),r);async function a(){if(!t)throw new g(`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 g(`no-access`,`This sign-in has no access to ${e.repo}.`);let r=await i(t);return M(t,e.manage,n,r,{read:o,readAt:async(e,t)=>(await a()).readAt(e,t)},ue)}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(N(e))return`no-access`;throw e}},async lastRun(){try{return await(await s()).lastRun()}catch(e){if(N(e))return;throw e}},async start(e){await(await s()).start(e)},async rebuild(){await(await s()).rebuild?.()}}}var P=/cloudflare/i,F=100,me=`mutation ($input: CreateCommitOnBranchInput!) {
3
- createCommitOnBranch(input: $input) { commit { oid } }
4
- }`;function I(e,t){let n=`${t}/`;return[...e.keys()].filter(e=>e.startsWith(n)).sort()}var L=class n{user;pages;editors;ownerAccess;updates;drafts;scheduledBuilds;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=C(e.repo),this.branch=e.branch,this.user=e.user,this.onSignOut=e.onSignOut,this.author=e.author,this.pinned=e.revision;let t=ne(this.api,this.repo,e.ownerTokenLink,e.ownerRedirect);this.owner=t,this.ownerAccess=t.access,this.pages=ae(()=>t.api()??this.api,this.repo),this.editors=te(this.api,t.api,this.repo,this.user.login),this.contentOnly=e.contentOnly===!0,this.contentOnly?e.code&&(this.updates=pe({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=M(this.api,t.api,this.repo,this.branch,this),this.drafts=l(this,this.draftHost()),this.scheduledBuilds=ce(e=>this.read(e))}async repositoryVisibility(){let e=await S(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)}`;return{liveBranch:this.branch,branchStore:e=>new n({...this.options,branch:e}),createBranch:async(t,n)=>{if((await x(this.api,`${e}/git/refs`,{method:`POST`,body:{ref:`refs/heads/${t}`,sha:n},allow:[422]})).status===422)throw new i(`exists`,`There's already a draft called ${t}.`)},deleteBranch:async e=>{await x(this.api,t(e),{method:`DELETE`,allow:[404,422]})},mergeBase:async t=>{let n=await x(this.api,`${e}/compare/${encodeURIComponent(this.branch)}...${encodeURIComponent(t)}`,{allow:[404]});if(n.status===404)throw new i(`not-found`,`There's no draft ${t}.`);return(await n.json()).merge_base_commit.sha},listBranches:async t=>(await S(this.api,`${e}/git/matching-refs/heads/${encodeURIComponent(t)}`)).map(e=>e.ref.replace(/^refs\/heads\//,``)),openReview:async({branch:t,title:n,description:r})=>{let a=await x(this.api,`${e}/pulls`,{method:`POST`,body:{title:n,head:t,base:this.branch,body:r},allow:[403,404,422]});if(a.ok)return{url:(await a.json()).html_url};if(a.status!==422)throw new i(`no-reviews`,`This sign-in can't open pull requests on the site's repository.`);let o=decodeURIComponent(this.repo).split(`/`)[0],s=new URLSearchParams({head:`${o}:${t}`,state:`open`}),[c]=await S(this.api,`${e}/pulls?${s}`);if(!c)throw new y(422,`GitHub couldn't open the pull request.`);return{url:c.html_url}}}}async revision(){return this.pinned=await this.head(),this.pinned}async head(){return(await S(this.api,`/repos/${this.repo}/git/ref/heads/${encodeURIComponent(this.branch)}`)).object.sha}tree(e){let t=this.trees.get(e);return t||(t=S(this.api,`/repos/${this.repo}/git/trees/${e}?recursive=1`).then(t=>{if(t.truncated)throw new y(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=x(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+=F){let t=r.slice(e,e+F),n=t.map((e,t)=>`f${t}: object(oid: "${e}") { ... on Blob { text isBinary } }`),o=await S(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 x(this.api,`/repos/${this.repo}/git/blobs/${n}`,{accept:`application/vnd.github.raw+json`});return new Uint8Array(await r.arrayBuffer())}async list(e){return I(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=>I(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 S(this.api,`${o}/git/blobs`,{method:`POST`,body:{content:_(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 S(this.api,`${o}/git/commits/${r}`),l=await S(this.api,`${o}/git/trees`,{method:`POST`,body:{base_tree:c.tree.sha,tree:s}}),u=await S(this.api,`${o}/git/commits`,{method:`POST`,body:{message:n,tree:l.sha,parents:[r],author:{...i,date:new Date().toISOString()}}});if((await x(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 y(422,`GitHub couldn't save the changes.`):new t;return this.pinned=u.sha,{revision:u.sha}}catch(e){throw e instanceof y&&(e.status===403||e.status===404)?new g(`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?_(e.bytes):m(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 S(this.api,`/graphql`,{method:`POST`,body:{query:me,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 g(`cant-publish`,`This GitHub account can't publish to the site.`):new y(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 S(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 S(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 S(this.api,`/repos/${this.repo}/deployments?sha=${e}&per_page=5`))[0];if(t){let[n]=await S(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 S(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 y)return{state:`unknown`};throw e}}async cloudflareBuild(e){let t=await x(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=>P.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 x(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=>P.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 x(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 x(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(`/${s}.yml`));return r.find(e=>/deploy|pages/i.test(`${e.path??``} ${e.name??``}`))??r[0]}async runProblem(e){let t=await x(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:u(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()}},R={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 z(e){let t=R[String(e.problem)]??`unavailable`,n=typeof e.installUrl==`string`&&/^https:\/\//.test(e.installUrl)?e.installUrl:void 0;return new g(t,`The sign-in service said: ${String(e.problem??`no answer`)}.`,n)}function B(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 V(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}async function H(){let e=V(crypto.getRandomValues(new Uint8Array(32))),t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return{verifier:e,challenge:V(new Uint8Array(t))}}function U(){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 W=`goodfellow_sign_in`,G=`goodfellow_sign_in_error`,K=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 g(`unavailable`,`Couldn't reach the sign-in service: ${e.message}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw z(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 g(`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 g(`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 q(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 g(`no-access`,`The sign-in service gave no token for the code repository.`);return i.code.token}}}var J=`main`;function Y(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 X(e){let t=new Map;async function n(e,t){if(t.default_branch===J)return;let n=`/repos/${C(t.full_name)}`,r=await S(e,`${n}/git/ref/heads/${t.default_branch}`);await x(e,`${n}/git/refs`,{method:`POST`,body:{ref:`refs/heads/${J}`,sha:r.object.sha}}),await x(e,n,{method:`PATCH`,body:{default_branch:J}}),await x(e,`${n}/git/refs/heads/${t.default_branch}`,{method:`DELETE`})}async function r(e,t){try{return(await S(e,`/repos/${C(t.full_name)}/pages`,{method:`POST`,body:{build_type:`workflow`}})).html_url}catch(e){if(e instanceof y&&[403,404,409,422].includes(e.status))return;throw e}}async function i(e,t,n){try{return await x(e,`/repos/${C(t.full_name)}/pages`,{method:`PUT`,body:{cname:n}}),!0}catch(e){if(e instanceof y&&[400,403,404,409,422].includes(e.status))return!1;throw e}}async function a(t,n,r){let i=`/repos/${C(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 S(t,`${i}/git/blobs`,{method:`POST`,body:{content:_(e.bytes),encoding:`base64`}});a.push({path:e.path,mode:`100644`,type:`blob`,sha:n.sha})}try{let n=await S(t,`${i}/git/trees`,{method:`POST`,body:{tree:a}}),o=await S(t,`${i}/git/commits`,{method:`POST`,body:{message:r.message,tree:n.sha,parents:[],...e.author&&{author:{...e.author,date:new Date().toISOString()}}}});await x(t,`${i}/git/refs/heads/${J}`,{method:`PATCH`,body:{sha:o.sha,force:!0}})}catch(e){throw e instanceof y&&(e.status===403||e.status===404)?new f(`not-allowed`,`This sign-in can't write the site's files, or its build setup.`):e}}async function o(e,t){return(await x(e,`/repos/${C(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 b(()=>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 x(u,`/repos/${C(c)}/keys`,{method:`POST`,body:{title:`${s}'s builds`,key:d.publicKey,read_only:!0}});let f=`/repos/${C(s)}/actions/secrets`,p=await S(l,`${f}/public-key`),m=await r(d.privateKey,h(p.key));await x(l,`${f}/${o}`,{method:`PUT`,body:{encrypted_value:_(m),key_id:p.key_id}})}return!0}catch(e){if(e instanceof y&&[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 he(e){let t=await S(e,`/user`);async function n(t,n){return(await x(e,`/repos/${C(`${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 S(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 f(`name-taken`,`There's already a repository called ${t.owner.path}/${t.name}.`);try{return{repo:await S(e,r,{method:`POST`,body:{name:t.name,private:t.private,description:t.description,auto_init:!0}}),api:e}}catch(e){throw e instanceof y&&e.status===422?new f(`name-invalid`,`GitHub can't use "${t.name}" as a repository name.`):e instanceof y&&(e.status===403||e.status===404)?new f(`not-allowed`,`This sign-in can't create repositories in ${t.owner.path}.`):e}}}}function ge(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 _e(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 f(`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 g(`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 _e(e){switch(e.problem){case`name-taken`:return new f(`name-taken`,`There's already a repository with that name.`);case`name-invalid`:return new f(`name-invalid`,`GitHub can't use that as a repository name.`);case`not-allowed`:return new f(`not-allowed`,`This sign-in can't create repositories there.`);case`not-installed`:return new f(`not-installed`,`Goodfellow isn't installed there.`,e.installUrl);default:return z(e)}}function Z(e={}){let t=(e.apiUrl??`https://api.github.com`).replace(/\/$/,``),n=Y(e.webUrl),r=e.fetch??((e,t)=>globalThis.fetch(e,t)),i=e.location??U(),a=e.signIn,o=a&&i&&!B(i.href())?new K(a,r):void 0,s=v(`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(W),a=e.searchParams.get(G);if(!n&&!a)return null;e.searchParams.delete(W),e.searchParams.delete(G),i.replace(e.toString());let c=s.load();if(s.clear(),a||!n||!c||!o)throw z({problem:a??`cancelled`});let l=await o.session(n,c);return X(ge(o,t,r,l))},async signInWithToken(e){let n=e.trim();if(!n)throw new g(`invalid`,`Paste a token to sign in.`);return X(await he({apiUrl:t,token:n,fetch:r}))},async startRedirect({install:e}={}){if(!o||!i)throw new g(`unavailable`,`Signing in with GitHub isn't available here.`);await o.health();let{verifier:t,challenge:n}=await H();s.save(t,!1),i.assign(o.startUrl({purpose:`setup`,back:i.href(),challenge:n,remember:!1,install:e}))}}}function Q(e){return e instanceof g&&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 ve(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=v(`goodfellow:github:${e.repo}`,e.storage),o=v(`goodfellow:github:pending:${e.repo}`,e.storage),s=e.fetch??((e,t)=>globalThis.fetch(e,t)),c=e.location??U(),l=e.signIn,u=l&&c&&!B(c.href())?new K(l,s):void 0,d=()=>e.contentOnly?e.code:void 0;function f(e,t){a.save(e.type===`token`?e.token:JSON.stringify(e),t)}function p(){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 m(t,n,{install:r}={}){if(!u||!c)throw new g(`unavailable`,`Signing in with GitHub isn't available here.`);r||await u.check(e.repo,t);let{verifier:i,challenge:a}=await H();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 h(n,o){let c=q(u,n,e=>f({type:`worker`,session:e.session},o),e.code);f({type:`worker`,session:n.session},o);let l={apiUrl:t,token:c.token,fetch:s},d=await S(l,`/repos/${C(e.repo)}`),{user:p}=n;return new L({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:p.login,name:p.name,avatarUrl:p.avatarUrl},author:{name:p.name||p.login,email:p.email},onSignOut:()=>{a.clear(),b(c.current())},ownerTokenLink:{url:i.owner,label:`owner.token.create`},ownerRedirect:e=>m(`owner`,!1,e)})}function _(e){x({apiUrl:t,token:e,fetch:s},`/installation/token`,{method:`DELETE`}).catch(()=>{})}function b(e){_(e.token),e.code&&_(e.code.token)}async function w(e,t,n){let r=u;try{let i=q(r,await r.session(t,n,d()),()=>{},d());e.useOwnerSignIn(i.token,()=>b(i.current()),d()?i.codeToken:void 0)}catch(t){e.ownerSignInFailed(t)}}async function T(){if(!c)return;let e=new URL(c.href()),t=e.searchParams.get(W),n=e.searchParams.get(G);if(!t&&!n)return;e.searchParams.delete(W),e.searchParams.delete(G),c.replace(e.toString());let r=o.load();o.clear();let i=r?JSON.parse(r):void 0;if(!i||!u)throw new g(`redirect-failed`,`Signing in with GitHub didn't finish in this tab.`);if(i.purpose===`owner`){let e=await E();if(!e)throw new g(`redirect-failed`,`Sign in again, then sign in as an owner.`);return n?e.ownerSignInFailed(z({problem:n})):t&&await w(e,t,i.verifier),e}if(n||!t)throw z({problem:n});return h(await u.session(t,i.verifier,d()),i.remember)}async function E(){let e=p();if(!e)return null;try{return e.type===`token`?await D(e.token):u?await h(await u.token(e.session,d()),a.remembered()):(a.clear(),null)}catch(e){throw Q(e)&&a.clear(),e}}async function D(n){let o={apiUrl:t,token:n,fetch:s},c=await S(o,`/user`),l;try{l=await S(o,`/repos/${C(e.repo)}`)}catch(t){throw t instanceof y&&(t.status===404||t.status===403)?new g(`no-access`,`The GitHub account ${c.login} can't see ${e.repo}.`):t}if(l.permissions?.push===!1)throw new g(`cant-publish`,`The GitHub account ${c.login} can see ${e.repo} but can't publish to it.`);return new L({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=>m(`owner`,!1,e)}})}function O({token:n}){let r={apiUrl:t,token:typeof n==`string`?n:()=>n(),fetch:s},a,o=()=>(a??=e.branch?Promise.resolve(e.branch):S(r,`/repos/${C(e.repo)}`).then(e=>e.default_branch),a.catch(()=>{a=void 0}),a),c=async(t,n)=>new L({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:()=>Z({...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 T();return e===void 0?E():e},async signInWithToken(e,t){let n=e.trim();if(!n)throw new g(`invalid`,`Paste a token to sign in.`);let r=await D(n);return f({type:`token`,token:n},t),r},startRedirect(e,t){return m(`edit`,e,t)},server:O}}export{L as GitHubBackend,ve as github,j as githubPagesRecords,Z as githubSetup,Y as githubSetupTokenLinks,$ as githubTokenLinks};
@@ -1,6 +0,0 @@
1
- import{n as e,r as t,t as n}from"./store-5raQS3us.js";import{a as r,c as i,d as a,f as o,i as s,m as c,o as l,p as u,r as d,t as f}from"./setup-host-w4Qxug91.js";import{n as p,o as m,r as h,s as ee,t as g}from"./git-eGyMXUIu.js";var te=class extends Error{problem;name=`ScheduledBuildsError`;constructor(e,t){super(t),this.problem=e}};async function _(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 p(`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 g(i.status,`GitLab answered ${i.status}: ${t||i.statusText}`)}return i}async function v(e,t,n){return await(await _(e,t,n)).json()}var y=30,b=40,ne=`member:`,x=`invitation:`,S=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,C=/^[\w][\w.-]*$/;function w(e){return e>=b?`owner`:e>=y?`editor`:`viewer`}function T(e){return e===`owner`?b:y}function E(e){throw e instanceof g&&(e.status===401||e.status===403)?new a(`not-allowed`,`Changing editors on GitLab needs the Maintainer role in the project.`):e}function re(e,t,n,r){let i=`/projects/${encodeURIComponent(t)}`,o=`${i}/protected_branches/${encodeURIComponent(n)}`;async function s(t){let n=[];for(let r=1;r<=10;r++){let i=await v(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([s(`${i}/members/all`),s(`${i}/members`)]),a=new Set(n.map(e=>e.id)),c=t.find(e=>e.username.toLowerCase()===r.toLowerCase()),l=(c?.access_level??0)>=b,u=l?await s(`${i}/invitations`).catch(()=>[]):[],d=await _(e,o,{allow:[404]}),f=d.ok?(await d.json()).push_access_levels??[]:[],p=!d.ok||f.some(e=>e.access_level!==null&&e.access_level<=y);return{editors:[...t.map(e=>({id:`${ne}${e.id}`,login:e.username,name:e.name,avatarUrl:e.avatar_url,role:w(e.access_level),...!a.has(e.id)&&{inherited:!0},...e.id===c?.id&&{self:!0}})),...u.map(e=>({id:`${x}${e.invite_email}`,email:e.invite_email,role:w(e.access_level),invited:!0}))],manage:l?`yes`:`no`,editorsCanPublish:p}},async invite(t,n){let r=t.trim().replace(/^@/,``);if(r.includes(`@`)){if(!S.test(r))throw new a(`invalid`,`That isn't an email address.`);let t=await v(e,`${i}/invitations`,{method:`POST`,body:{email:r,access_level:T(n)}}).catch(E);if(t.status!==`success`){let e=typeof t.message==`string`?t.message:Object.values(t.message??{})[0];throw/already/i.test(e??``)?new a(`already`,`They've already been invited.`):new a(`invalid`,`GitLab didn't accept the invitation: ${e??t.status}`)}return}if(!C.test(r))throw new a(`invalid`,`That isn't a GitLab username or email address.`);let[o]=await v(e,`/users?${new URLSearchParams({username:r})}`);if(!o)throw new a(`not-found`,`There's no GitLab account named ${r}.`);try{await _(e,`${i}/members`,{method:`POST`,body:{user_id:o.id,access_level:T(n)}})}catch(e){if(e instanceof g&&e.status===409)throw new a(`already`,`${r} already edits the site.`);E(e)}},async setRole(t,n){await _(e,t.id.startsWith(x)?`${i}/invitations/${encodeURIComponent(t.id.slice(11))}`:`${i}/members/${t.id.slice(7)}`,{method:`PUT`,body:{access_level:T(n)}}).catch(E)},async remove(t){await _(e,t.id.startsWith(x)?`${i}/invitations/${encodeURIComponent(t.id.slice(11))}`:`${i}/members/${t.id.slice(7)}`,{method:`DELETE`}).catch(E)},async letEditorsPublish(){let t=t=>_(e,`${i}/protected_branches`,{method:`POST`,body:{name:n,push_access_level:t,merge_access_level:t,allow_force_push:!1}});await _(e,o,{method:`DELETE`,allow:[404]}).catch(E);try{await t(y)}catch(e){await t(b).catch(()=>void 0),E(e)}}}}var ie=`35.185.44.232`,D=`2600:1901:0:7b8a::`;function O(e,{apex:t,www:n}){return t&&n?[e,`www.${e}`]:[e]}function k(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:D,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=O(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 A(e,t){let n=`/projects/${encodeURIComponent(t)}/pages`,r=e=>`${n}/domains/${encodeURIComponent(e)}`;function i(e){throw e instanceof g&&(e.status===401||e.status===403)?new c(`not-allowed`,`Connecting a domain on GitLab needs the Maintainer role in the project.`):e}async function a(){let t=await _(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 _(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 v(e,r(t)).catch(i);if(n.verified)return n;let a=await _(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 v(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,l){let u=await a();u&&u.is_unique_domain_enabled===!1&&await _(e,n,{method:`PATCH`,body:{pages_unique_domain_enabled:!0}}).catch(i);for(let t of O(s,l))try{await _(e,`${n}/domains`,{method:`POST`,body:{domain:t,auto_ssl_enabled:!0}})}catch(n){if(n instanceof g&&n.status===400){if(/taken/i.test(n.message)){if((await _(e,r(t),{allow:[404]})).ok)continue;throw new c(`taken`,`Another GitLab Pages site already uses this domain.`)}throw new c(`invalid`,`GitLab Pages doesn't accept this domain.`)}i(n)}return k(t,s,l,await o(O(s,l)))},async records(e,n){return k(t,e,n,await o(O(e,n)))},async status(t){let n=await s(t),i=await _(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 v(e,r(t)).catch(i);if(!o.verified||!o.certificate)throw new c(`not-ready`,`The domain's certificate isn't ready yet.`);if(!a){await _(e,n,{method:`PATCH`,body:{pages_https_only:!0}}).catch(i);return}try{await _(e,n,{method:`PATCH`,body:{pages_https_only:!0,pages_primary_domain:t}})}catch(t){t instanceof g&&t.status===400||i(t),await _(e,n,{method:`PATCH`,body:{pages_https_only:!0}}).catch(i)}},async disconnect(t){for(let n of[t,`www.${t}`])await _(e,r(n),{method:`DELETE`,allow:[404]}).catch(i)}}}var j=`Goodfellow: build the site for a scheduled change at `,M=`GOODFELLOW_SCHEDULED_CHANGE`;function N(e){throw e instanceof g&&(e.status===401||e.status===403)?new te(`not-allowed`,`Adding pipeline schedules on GitLab needs the Developer role, with permission to merge to the main branch.`):e}function ae(e){return`${e.getUTCMinutes()} ${e.getUTCHours()} ${e.getUTCDate()} ${e.getUTCMonth()+1} *`}function oe(e){return`${e.toISOString().slice(0,16)}Z`}function se(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(oe(e),e)}let s=await v(e,`${a}?per_page=100`).catch(N),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 _(e,`${a}/${n.id}`,{method:`DELETE`,allow:[403,404]});for(let[t,r]of o){if(c.has(t))continue;let i=await v(e,a,{method:`POST`,body:{description:`${j}${t}`,ref:n,cron:ae(r),cron_timezone:`UTC`,active:!0}}).catch(N);await _(e,`${a}/${i.id}/variables`,{method:`POST`,body:{key:M,value:t,variable_type:`env_var`}}).catch(N)}}}}var P=`.gitlab-ci.yml`,F=`17 4 * * *`;function I(e){throw e instanceof g&&(e.status===401||e.status===403)?new l(`not-allowed`,`Setting up updates on GitLab needs the Maintainer role in the project.`):e}function L(e,t,n,a,o=`pages`){let s=`/projects/${encodeURIComponent(t)}`;async function c(){return v(e,`${s}/pipeline_schedules`)}async function u(){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 a(P))?.includes(`update --publish`))return`missing`;try{let[t,r]=await Promise.all([v(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 g&&e.status===403)return`needs-setup`;throw e}},async enable(){await _(e,s,{method:`PUT`,body:{ci_push_repository_for_job_token_allowed:!0}}).catch(I),await u().catch(I)||await _(e,`${s}/pipeline_schedules`,{method:`POST`,body:{description:`Rebuild the site and install Goodfellow's fixes each night`,ref:n,cron:F,cron_timezone:`UTC`,active:!0}}).catch(I)},async lastRun(){let t=await v(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 v(e,`${s}/pipelines/${n.id}/jobs?per_page=100`)).find(e=>e.name===o||e.name===`update`);if(!r)continue;let a=await _(e,`${s}/jobs/${r.id}/trace`,{allow:[403,404]}),c=a.ok?i(await a.text()):void 0;if(c)return{state:c.state,result:c,...t}}},async start(t){await _(e,`${s}/pipeline`,{method:`POST`,body:{ref:n,variables:[{key:`GOODFELLOW_UPDATE`,variable_type:`env_var`,value:t}]}}).catch(I)},nightly:{async supported(){return(await a(P))?.includes(`nightly`)??!1},async get(){try{let t=await u();return t?t.active?(await v(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 g&&e.status===403)return;throw e}},async set(t){let n=await u().catch(I);if(!n)throw new l(`missing`,`The site has no nightly schedule yet: turn on updates first.`);let i=`${s}/pipeline_schedules/${n.id}`;if(await _(e,i,{method:`PUT`,body:{active:t!==`off`}}).catch(I),t===`always`){let t={key:r,value:`always`};(await _(e,`${i}/variables/GOODFELLOW_NIGHTLY`,{method:`PUT`,body:t,allow:[404]}).catch(I)).status===404&&await _(e,`${i}/variables`,{method:`POST`,body:t}).catch(I)}else t===`changed`&&await _(e,`${i}/variables/${r}`,{method:`DELETE`,allow:[404]}).catch(I)}},async rebuild(){await _(e,`${s}/pipeline`,{method:`POST`,body:{ref:n,variables:[{key:`GOODFELLOW_REBUILD`,variable_type:`env_var`,value:`true`}]}}).catch(I)}}}function R(e){return e instanceof g&&(e.status===403||e.status===404)}function z(e){let{api:t,project:n}=e,r,i=()=>(r??=v(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()=>L(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(R(e))return`no-access`;throw e}},async enable(){await(await s()).enable?.()},async lastRun(){try{return await(await s()).lastRun()}catch(e){if(R(e))return;throw e}},async start(e){await(await s()).start(e)},async rebuild(){await(await s()).rebuild?.()}}}var B=100,V=50,H=RegExp(`\x1B\\[[\\d;]*[A-Za-z]`,`g`);function U(e){return e.name!==`rebuild`&&e.name!==`update`}function W(e,t){let n=`${t}/`;return[...e.keys()].filter(e=>e.startsWith(n)).sort()}var G=class r{user;pages;editors;updates;drafts;scheduledBuilds;contentOnly;options;api;project;branch;onSignOut;pinned;trees=new Map;blobs=new Map;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.pages=A(this.api,e.project),this.editors=re(this.api,e.project,this.branch,this.user.login),this.contentOnly=e.contentOnly===!0,!this.contentOnly)this.updates=L(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=z({api:this.api,project:t.project,webUrl:t.webUrl,open:e=>new r({api:this.api,project:t.project,branch:e,user:this.user,onSignOut:()=>{}})})}this.drafts=u(this,this.draftHost()),this.scheduledBuilds=se(this.api,e.project,this.branch,async()=>this.readAt(`.gitlab-ci.yml`,this.pinned??await this.revision()))}async repositoryVisibility(){let{visibility:e}=await v(this.api,`/projects/${this.project}`);return e===`public`||e===`internal`?e:`private`}draftHost(){let e=`/projects/${this.project}`;return{liveBranch:this.branch,branchStore:e=>new r({...this.options,branch:e}),createBranch:async(e,t)=>{if((await _(this.api,this.repo(`/branches?${new URLSearchParams({branch:e,ref:t})}`),{method:`POST`,allow:[400]})).status===400)throw new o(`exists`,`There's already a draft called ${e}.`)},deleteBranch:async e=>{await _(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 _(this.api,this.repo(`/merge_base?${t}`),{allow:[400,404]});if(!n.ok)throw new o(`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 v(this.api,this.repo(`/branches?${t}`))).map(e=>e.name).filter(t=>t.startsWith(e))},openReview:async({branch:t,title:n,description:r})=>{let i=await _(this.api,`${e}/merge_requests`,{method:`POST`,body:{source_branch:t,target_branch:this.branch,title:n,description:r,remove_source_branch:!0},allow:[403,404,409]});if(i.ok)return{url:(await i.json()).web_url};if(i.status!==409)throw new o(`no-reviews`,`This sign-in can't open merge requests on the site's project.`);let a=new URLSearchParams({source_branch:t,state:`opened`}),[s]=await v(this.api,`${e}/merge_requests?${a}`);if(!s)throw new g(409,`GitLab couldn't open the merge request.`);return{url:s.web_url}}}}repo(e){return`/projects/${this.project}/repository${e}`}async revision(){return this.pinned=await this.head(),this.pinned}async head(){return(await v(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(B),page:String(r)}),a=await _(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<B)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=_(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+=V){let r=i.slice(n,n+V),a=await v(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 _(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+=V){let i=await v(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+V)}}});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 v(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 g&&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:m(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 e=await v(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=e.id,{revision:e.id}}catch(e){throw e instanceof g?e.status===403?new p(`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 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 v(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 _(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 v(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 v(this.api,`/projects/${this.project}/pipelines?per_page=1`)).length>0)return{state:`building`};let{parent_ids:t=[]}=await v(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 g)return{state:`unknown`};throw e}}statuses(e){return v(this.api,this.repo(`/commits/${e}/statuses`))}async jobProblem(e){let[t]=await v(this.api,`/projects/${this.project}/pipelines?${new URLSearchParams({sha:e,per_page:`1`})}`);if(!t)return;let n=(await v(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 _(this.api,`/projects/${this.project}/jobs/${n.id}/trace`,{allow:[403,404]}),o=a.ok?await a.text():``,c=s(o),l=o.split(`
6
- `).map(e=>e.replace(H,``).replace(/^.*\r/,``)).filter(e=>e.startsWith(`$ `)).at(-1);return{step:c?`build`:(l?d(l):void 0)??`build`,detail:i,...c&&{cause:c}}}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 ce(){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=h(`goodfellow:gitlab-setup:pending`,e.storage),a=()=>e.location??ce();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 p(`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 v(s,`/user`);async function l(e,t){return(await _(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 v(s,t(e[r]))).id);for(let{reader:r,read:i}of e.links.reads)await _(s,`${t(e[i])}/job_token_scope/allowlist`,{method:`POST`,body:{target_project_id:n.get(r)}});e.links.updates&&await _(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 _(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:F,cron_timezone:`UTC`,active:!0}});return!0}catch(e){if(e instanceof g&&[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 v(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 f(`name-taken`,`There's already a project called ${e.owner.path}/${e.name}.`);let n;try{n=await v(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 g&&t.status===400?new f(`name-invalid`,`GitLab can't use "${e.name}" as a project name.`):t instanceof g&&(t.status===403||t.status===404)?new f(`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 _(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 g)||![400,403,404,409,422].includes(e.status))throw e;r.push(`domain-unavailable`)}}return t?.(`files`),await _(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:m(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 p(`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 p(`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 le=30;function $(){return{href:()=>window.location.href,assign:e=>window.location.assign(e),replace:e=>window.history.replaceState(window.history.state,``,e)}}function ue(e){let t=(e.url??`https://gitlab.com`).replace(/\/$/,``),n=`${t}/api/v4`,r=e.fetch??((e,t)=>globalThis.fetch(e,t)),i=h(`goodfellow:gitlab:${t}:${e.project}`,e.storage),a=h(`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 p(`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 v(u,`/user`),f;try{f=await v(u,`/projects/${encodeURIComponent(e.project)}`)}catch(t){throw t instanceof g&&(t.status===404||t.status===403)?new p(`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)<le)throw new p(`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 p(`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 u({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):v(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:ee(`@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 p&&i.clear(),e}},async signInWithToken(e,t){let n=e.trim();if(!n)throw new p(`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:u}}export{G as GitLabBackend,ue as gitlab,k as gitlabPagesRecords,Q as gitlabSetup,X as redirectUri};
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./dist-C20K9oCc.js","./store-5raQS3us.js","./setup-host-w4Qxug91.js","./git-eGyMXUIu.js","./preload-helper-khBccGFq.js","./dist-cedgnWG_.js"])))=>i.map(i=>d[i]);
2
- import{i as e}from"./store-5raQS3us.js";import{t}from"./preload-helper-khBccGFq.js";function n(e){if(e)try{let t=new URL(e.url),n=t.hostname===`localhost`||t.hostname===`127.0.0.1`;return(t.protocol===`https:`||t.protocol===`http:`&&n)&&t.pathname===`/`&&!t.search&&!t.hash?t.origin:void 0}catch{return}}var r=/^[ \t]*admin:[ \t]*\{[^\n]*\},?[ \t]*\n/m;function i(e){let t=r.exec(e)?.[0],n=t&&/url:\s*"([^"\\]+)"/.exec(t)?.[1];if(t&&n)return{url:n,.../checked:\s*true/.test(t)&&{checked:!0}}}function a(e,t,{start:n=!0,end:r=!0}={}){let i=0,a=e.length;for(;n&&i<a&&t.includes(e.charAt(i));)i++;for(;r&&a>i&&t.includes(e.charAt(a-1));)a--;return e.slice(i,a)}var o=`goodfellow:broker-connect`;function s(e){return e.startsWith(`.github/`)||e===`.gitlab-ci.yml`||e.startsWith(`.gitlab/`)}function c(t,n){let r={refused:[],confirm:[]};for(let i of t){let{path:t}=i;if(s(t)||t.startsWith(`/`)||t.split(`/`).includes(`..`))r.refused.push(t);else if(t.startsWith(`content/code/`))r.confirm.push({path:t,kind:`custom-code`});else if(!e(t))r.confirm.push({path:t,kind:`code`});else if(t===`content/site.json`&&`content`in i){let e;try{e=JSON.parse(i.content).url}catch{e=void 0}(e??void 0)!==(n??void 0)&&r.confirm.push({path:t,kind:`site-address`})}}return r}var l=class extends Error{problem;name=`BrokerRefusedError`;constructor(e,t){super(t),this.problem=e}},u=[`revision`,`read`,`readBytes`,`list`,`readFiles`,`fileSizes`,`write`,`changedPaths`],d={methods:[`read`,`readBytes`,`list`]},f={name:`draft`,data:[`name`],methods:[`changes`,`paths`,`publish`,`submitForReview`,`discard`],objects:{store:{methods:u}}},p={data:[`user`,`contentOnly`],methods:[...u,`deployStatus`,`history`,`readAt`,`repositoryVisibility`,`signOut`],sync:{filesAt:d},objects:{pages:{data:[`severalDomains`],methods:[`site`,`connect`,`records`,`status`,`secure`,`disconnect`]},editors:{methods:[`list`,`invite`,`setRole`,`remove`,`letEditorsPublish`]},ownerAccess:{data:[`tokenLink`,`active`,`problem`],methods:[`forget`,`startRedirect`,`requestToken`]},updates:{methods:[`setup`,`enable`,`lastRun`,`start`,`rebuild`],objects:{code:{data:[`repo`,`webUrl`],methods:[`read`,`history`,`readAt`]},nightly:{methods:[`supported`,`get`,`set`]}}},drafts:{methods:[`create`,`open`,`list`],returns:{create:f,open:f}},scheduledBuilds:{methods:[`timing`,`sync`]}}};function m(e){if(!(e instanceof Error))return{name:`Error`,message:String(e),fields:{}};let t={};for(let[n,r]of Object.entries(e))[`string`,`number`,`boolean`].includes(typeof r)&&(t[n]=r);return{name:e.name,message:e.message,fields:t}}function h(e){return e instanceof Error?{__error:m(e)}:e}function g(e,t,n={}){let r=new Map([[0,{target:t,shape:p,prefix:``}]]),i=1;function a(e,t,r,i){let o=e,s={};for(let e of t.data??[])o[e]!==void 0&&(s[e]=h(o[e]));let c=(t.methods??[]).filter(e=>typeof o[e]==`function`||n.extra?.[`${r}${e}`]!==void 0);for(let e of Object.keys(t.sync??{}))typeof o[e]==`function`&&c.push(e);let l={};for(let[e,n]of Object.entries(t.objects??{})){let t=o[e];typeof t==`object`&&t&&(l[e]=a(t,n,`${r}${e}.`,i))}return{handle:i,data:s,methods:c,objects:l}}let o=()=>a(t,p,``,0);function s(e,t){let n=r.get(e);if(!n)return;let i=n.target,a=n.shape,o=n.prefix;for(let e of t.slice(0,-1))if(a=a?.objects?.[e],i=i?.[e],o+=`${e}.`,!a||typeof i!=`object`||!i)return;let s=t.at(-1)??``;if((a?.methods?.includes(s)||Object.hasOwn(a?.sync??{},s))&&a)return{target:i,shape:a,method:s,name:`${o}${s}`}}async function c(e){let t=s(e.handle,e.path);if(!t)throw new l(`not-here`,`The broker doesn't offer that.`);let{target:o,shape:c,method:u,name:d}=t,f=Array.isArray(e.args)?e.args:[],p=n.extra?.[d];if(c.sync?.[u]){let t=c.sync[u],[r,i]=e.then??[``,[]];if(!t.methods?.includes(r))throw new l(`not-here`,`The broker doesn't offer that.`);await n.check?.({path:`${d}.${r}`,args:[...f,...i],target:o});let a=o[u].apply(o,f);return a[r].apply(a,i)}await n.check?.({path:d,args:f,target:o});let m=p?await p(...f):await o[u].apply(o,f),h=c.returns?.[u];if(h&&typeof m==`object`&&m){let e=i++,t=`${h.name??d}.`;return r.set(e,{target:m,shape:h,prefix:t}),{__object:a(m,h,t,e)}}return m}return e.onmessage=async t=>{let n=t.data;if(n?.type===`call`&&Array.isArray(n.path))try{let t=await c(n);e.postMessage({type:`answer`,id:n.id,ok:!0,value:t,state:o()})}catch(t){e.postMessage({type:`answer`,id:n.id,ok:!1,error:m(t),state:o()})}},e.postMessage({type:`state`,state:o()}),()=>{e.onmessage=null,r.clear()}}var _={anthropic:{name:`Claude`,keyUrl:`https://platform.claude.com/settings/keys`,needsKey:!0,models:[`claude-opus-5-5`,`claude-sonnet-5-5`,`claude-haiku-4-5`]},openai:{name:`OpenAI`,keyUrl:`https://platform.openai.com/api-keys`,needsKey:!0,baseUrl:`https://api.openai.com/v1`,structured:`json_schema`},gemini:{name:`Google Gemini`,keyUrl:`https://aistudio.google.com/apikey`,needsKey:!0,baseUrl:`https://generativelanguage.googleapis.com/v1beta/openai`,structured:`json_schema`},groq:{name:`Groq`,keyUrl:`https://console.groq.com/keys`,needsKey:!0,baseUrl:`https://api.groq.com/openai/v1`,structured:`json_object`},mistral:{name:`Mistral`,keyUrl:`https://console.mistral.ai/api-keys`,needsKey:!0,baseUrl:`https://api.mistral.ai/v1`,structured:`json_schema`},openrouter:{name:`OpenRouter`,keyUrl:`https://openrouter.ai/settings/keys`,needsKey:!0,baseUrl:`https://openrouter.ai/api/v1`,structured:`json_schema`},ovhcloud:{name:`OVHcloud AI Endpoints`,needsKey:!1,baseUrl:`https://oai.endpoints.kepler.ai.cloud.ovh.net/v1`,structured:`json_object`,models:[`gpt-oss-120b`]},custom:{name:`OpenAI-compatible`,needsKey:!1,structured:`json_object`},manual:{name:`Chat app`,needsKey:!1}};function v(e,t){let n=t?e.split(t).join(`[key]`):e;return n=n.replace(/\b(sk|gsk|AIza)[-_A-Za-z0-9]{12,}/g,`[key]`),n}var y=`https://api.anthropic.com`,b=10485760,x=[`content-type`,`accept`,`anthropic-version`,`anthropic-beta`];function S(e,t,n){return e===`anthropic`?t===`POST`&&n===`v1/messages`:t===`POST`&&n===`chat/completions`||t===`GET`&&n===`models`}function C(e,t){return Response.json({error:{message:t}},{status:e,headers:{"cache-control":`no-store`}})}function w(e,t={}){let n=t.fetch??((e,t)=>fetch(e,t)),r=Object.entries(e).flatMap(([e,t])=>t&&(typeof t==`string`||t.baseUrl)?[[e,t]]:[]),i=new Map(r);async function o(e,t,r){let o=t,s=i.get(o);if(!s)return C(404,`This site has no key for that service.`);if(!S(o,e.method,r))return C(404,`The AI assistant doesn't use that.`);let c=typeof s==`string`?s:s.key,l=o===`anthropic`?y:typeof s==`object`?s.baseUrl:_[o].baseUrl??``;if(!l)return C(404,`This site has no address for that service.`);let u=e.method===`GET`?void 0:await e.arrayBuffer();if(u&&u.byteLength>b)return C(413,`That request is too large.`);let d=new Headers;for(let t of x){let n=e.headers.get(t);n&&d.set(t,n)}c&&(o===`anthropic`?d.set(`x-api-key`,c):d.set(`authorization`,`Bearer ${c}`));let f=`${a(l,`/`,{start:!1})}/${r}${new URL(e.url).search}`,p;try{p=await n(f,{method:e.method,headers:d,body:u,signal:e.signal})}catch(e){if(e.name===`AbortError`)throw e;return C(502,`The AI service couldn't be reached.`)}if(!p.ok){let e=v(await p.text().catch(()=>``),c);return new Response(e,{status:p.status,headers:{"content-type":p.headers.get(`content-type`)??`text/plain`,"cache-control":`no-store`}})}return new Response(p.body,{status:p.status,headers:{"content-type":p.headers.get(`content-type`)??`application/json`,"cache-control":`no-store`}})}return{services:[...i.keys()],forward:o}}var T=new Set([`write`,`draft.store.write`]);function E(e,t){let n=c(e,t);if(n.refused.length>0)return{action:`refuse`,paths:n.refused};let r=new Map;for(let{path:e,kind:t}of n.confirm)r.set(t,[...r.get(t)??[],e]);let i=[...r].map(([e,t])=>({kind:e,paths:t}));return i.length>0?{action:`ask`,questions:i}:{action:`allow`}}function D(e){if(typeof e==`string`)return e;let t=e?.login;return typeof t==`string`?t:``}async function O(e,t){let{path:n,args:r,target:i}=e;return T.has(n)?E(r[0]??[],t):n===`draft.publish`?E(await i.changes(),t):n===`updates.start`?{action:`ask`,questions:[{kind:`update`,release:String(r[0])}]}:n===`editors.invite`||n===`editors.setRole`?{action:`ask`,questions:[{kind:`editors`,who:D(r[0]),role:String(r[1])}]}:n===`editors.letEditorsPublish`?{action:`ask`,questions:[{kind:`editors`,who:``}]}:{action:`allow`}}var k={title:`Sign in`,loading:`Loading…`,framed:`This page can't be shown inside another page. Open it on its own.`,noConfig:`This sign-in page isn't set up yet: it needs a broker.json beside it, naming the site it signs in to. See the token broker page in Goodfellow's documentation.`,signInTitle:`Sign in to edit {site}`,signInIntro:`This page keeps your sign-in and AI keys where the site's pages can't reach them, and shows the admin panel from here.`,signInRedirect:`Sign in with {host}`,signInToken:`Or sign in with an access token`,tokenLabel:`Access token`,remember:`Stay signed in on this device`,signInButton:`Sign in`,signingIn:`Signing in…`,signInError:`That didn't work: {message}`,noSiteAddress:`The site has no address yet, so there's no admin panel to show. Set its address in Site Settings first, or ask its owner to.`,badSiteAddress:`The site's address, {address}, isn't one this page can show the admin panel from.`,signedInAs:`Signed in as {name}`,aiKeys:`AI keys`,signOut:`Sign out`,adminFrame:`Admin panel`,confirmTitle:`Publish this?`,confirmIntro:`The admin panel asked to publish changes that need you to say so here, where nothing it runs can say so for you:`,confirmCode:`The site's code, which runs when the site is built:`,confirmCustomCode:`Code that runs on the site's pages:`,confirmSiteAddress:`A new Site address, which is where this page shows the admin panel from. Only publish it if you changed it yourself:`,confirmUpdate:`Installing Goodfellow {release}, which changes the site's packages.`,confirmEditors:`Giving {who} access to edit the site{role}.`,confirmEditorsPublish:`Letting the site's editors publish to it.`,confirmPublish:`Publish`,confirmAllow:`Allow`,cancel:`Cancel`,refusedWorkflow:`The token broker never changes the site's workflows, which run with its secrets: {paths}.`,declined:`You chose not to publish this.`,ownerTitle:`Owner token`,ownerIntro:`Create a token that can manage the site, then paste it here. This page keeps it for as long as it's open, and the admin panel never sees it.`,ownerCreate:`Create a token`,ownerLabel:`Owner token`,ownerUse:`Use this token`,aiTitle:`AI keys`,aiIntro:`The AI assistant asks these services through this page, with your keys, so the admin panel never sees them. Leave a service empty to not use it.`,aiRemember:`Remember these keys on this device`,aiSave:`Save`};function A(e,t={}){return k[e].replace(/\{(\w+)\}/g,(e,n)=>t[n]??e)}var j=`goodfellow:broker:route`,M=`goodfellow:broker:ai`,N=`goodfellow.config.tsx`,P=Object.keys(_).filter(e=>e!==`custom`&&e!==`manual`&&(e===`anthropic`||_[e].baseUrl));function F(e,t={},...n){let r=document.createElement(e);for(let[e,n]of Object.entries(t))r.setAttribute(e,n);return r.append(...n),r}function I(e){return e instanceof Error?e.message:String(e)}function L(e){let{repo:t,project:n}=e.options;return typeof t==`string`?t:typeof n==`string`?n:e.package}function R(){for(let e of[sessionStorage,localStorage])try{let t=e.getItem(M);if(t)return JSON.parse(t)}catch{}return{}}function z(e,t){B(),(t?localStorage:sessionStorage).setItem(M,JSON.stringify(e))}function B(){sessionStorage.removeItem(M),localStorage.removeItem(M)}async function V(e){let t=await e.revision(),r=JSON.parse(await e.read(`content/site.json`)??`{}`);if(typeof r.url!=`string`||!r.url)return{problem:`noSiteAddress`};let a;try{a=new URL(r.url.replace(/\/?$/,`/`))}catch{return{problem:`badSiteAddress`}}let o=a.hostname===`localhost`||a.hostname===`127.0.0.1`;if(a.protocol!==`https:`&&!(a.protocol===`http:`&&o))return{problem:`badSiteAddress`};let s=await e.readAt(N,t).catch(()=>void 0),c=s?i(s):void 0;return{url:`${(c?.checked?n(c):void 0)??a.origin}${a.pathname}admin/`,siteUrl:r.url}}async function H({root:e,config:t,hosts:n}){document.title=A(`title`);let r=(...t)=>e.replaceChildren(...t);if(window.top!==window){r(F(`p`,{class:`broker-note`},A(`framed`)));return}let i=new URLSearchParams(location.search).get(`site`),a=t?.sites.find(e=>!i||L(e)===i)??t?.sites[0],s=a&&Object.hasOwn(n,a.package)?n[a.package]:void 0,c=s&&(await s())[a?.export??``];if(!a||typeof c!=`function`){r(F(`p`,{class:`broker-note`},A(`noConfig`)));return}let u=c(a.options),d=()=>{location.hash&&sessionStorage.setItem(j,location.hash)};d(),window.addEventListener(`hashchange`,d),r(F(`p`,{class:`broker-note`},A(`loading`)));let f=null,p;try{f=await u.restore()}catch(e){p=e}f?await h(f):m(p);function m(e){let t=F(`form`,{class:`broker-sign-in`}),n=F(`input`,{type:`checkbox`,id:`broker-remember`}),i=F(`input`,{type:`password`,id:`broker-token`,autocomplete:`off`}),o=F(`p`,{class:`broker-error`,role:`alert`});e!==void 0&&(o.textContent=A(`signInError`,{message:I(e)}));let s=F(`button`,{type:`submit`},A(`signInButton`)),c=async e=>{s.disabled=!0,o.textContent=A(`signingIn`);try{await h(await e())}catch(e){o.textContent=A(`signInError`,{message:I(e)}),s.disabled=!1}};if(t.append(F(`h1`,{},A(`signInTitle`,{site:L(a)})),F(`p`,{},A(`signInIntro`)),o),u.canRedirect){let e=F(`button`,{type:`button`,class:`broker-primary`},A(`signInRedirect`,{host:u.name}));e.addEventListener(`click`,()=>void u.startRedirect(n.checked).catch(e=>{o.textContent=A(`signInError`,{message:I(e)})})),t.append(F(`div`,{},e))}if(u.tokenLinks){let e=F(`ul`,{});for(let t of u.tokenLinks)e.append(F(`li`,{},F(`a`,{href:t.url,target:`_blank`,rel:`noreferrer`},t.url)));t.append(F(`h2`,{},A(`signInToken`)),e,F(`label`,{for:`broker-token`},A(`tokenLabel`)),i,F(`label`,{class:`broker-check`},n,` ${A(`remember`)}`),F(`div`,{},s))}t.addEventListener(`submit`,e=>{e.preventDefault(),i.value.trim()&&c(()=>u.signInWithToken(i.value.trim(),n.checked))}),r(t)}async function h(e){let t=await V(e).catch(e=>({problem:`signInError`,error:e}));if(`problem`in t){r(F(`p`,{class:`broker-note`,role:`alert`},A(t.problem,{address:``,message:`error`in t?I(t.error):``})));return}let n=new URL(t.url).origin,i=sessionStorage.getItem(j)??``,a=F(`iframe`,{class:`broker-frame`,title:A(`adminFrame`),src:`${t.url}${i.startsWith(`#`)?i:``}`,sandbox:`allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads allow-modals`,allow:`clipboard-write`}),s=()=>{window.removeEventListener(`message`,p),f?.(),e.signOut(),B(),sessionStorage.removeItem(j),m()},c=F(`button`,{type:`button`},A(`aiKeys`));c.addEventListener(`click`,()=>S(()=>a.contentWindow?.location.replace(a.src)));let d=F(`button`,{type:`button`},A(`signOut`));d.addEventListener(`click`,s),r(F(`header`,{class:`broker-bar`},F(`span`,{},A(`signedInAs`,{name:e.user.name||e.user.login})),c,d),a);let f,p=r=>{if(r.source!==a.contentWindow||r.origin!==n||r.data?.type!==`goodfellow:broker-ready`)return;f?.();let i=new MessageChannel,c=new MessageChannel;f=g(i.port1,e,{async check(e){let n=await O(e,t.siteUrl);if(n.action===`refuse`)throw new l(`workflow`,A(`refusedWorkflow`,{paths:n.paths.join(`, `)}));if(n.action===`ask`&&!await b(n.questions))throw new l(`declined`,A(`declined`))},extra:{signOut:s,"ownerAccess.requestToken":()=>x(e)}}),c.port1.onmessage=e=>void v(c.port1,e.data);let d={hostName:u.name,redirectAddressesListed:u.canRedirect&&u.redirectAddressesListed===!0,aiServices:Object.keys(R())};a.contentWindow?.postMessage({type:o,account:d},n,[i.port2,c.port2])};window.addEventListener(`message`,p)}async function v(e,t){if(t?.type===`route`&&typeof t.hash==`string`){sessionStorage.setItem(j,t.hash);return}if(t?.type!==`ai`)return;let[n=``,...r]=t.path.split(`?`)[0]?.split(`/`)??[],i=t.path.includes(`?`)?t.path.slice(t.path.indexOf(`?`)):``,a=new Request(`https://broker.invalid/${r.join(`/`)}${i}`,{method:t.method,headers:t.headers,...t.body&&t.method!==`GET`&&{body:t.body}}),o=await w(R()).forward(a,n,r.join(`/`)),s=await o.arrayBuffer(),c={type:`ai`,id:t.id,status:o.status,headers:[...o.headers.entries()],body:s};e.postMessage(c,[s])}function y(e,t,n){return new Promise(r=>{let i=F(`dialog`,{class:`broker-dialog`},F(`h2`,{},e),...t),a=F(`div`,{class:`broker-actions`});for(let e of n){let t=F(`button`,{type:`button`,...e.primary&&{class:`broker-primary`}},e.label);t.addEventListener(`click`,()=>i.close(e.value?`yes`:`no`)),a.append(t)}i.append(a),i.addEventListener(`close`,()=>{i.remove(),r(i.returnValue===`yes`)}),document.body.append(i),i.showModal()})}function b(e){let t=[F(`p`,{},A(`confirmIntro`))],n=!1;for(let r of e)if(r.kind===`update`)t.push(F(`p`,{},A(`confirmUpdate`,{release:r.release})));else if(r.kind===`editors`)t.push(F(`p`,{},r.who?A(`confirmEditors`,{who:r.who,role:r.role?` (${r.role})`:``}):A(`confirmEditorsPublish`)));else{n=!0;let e=r.kind===`code`?`confirmCode`:r.kind===`custom-code`?`confirmCustomCode`:`confirmSiteAddress`;t.push(F(`p`,{},A(e)),F(`ul`,{},...r.paths.map(e=>F(`li`,{},F(`code`,{},e)))))}return y(A(`confirmTitle`),t,[{label:A(`cancel`),value:!1},{label:A(n?`confirmPublish`:`confirmAllow`),value:!0,primary:!0}])}async function x(e){let t=e.ownerAccess;if(!t)throw new l(`not-here`,`This site's host has no owner token.`);let n=F(`input`,{type:`password`,id:`broker-owner-token`,autocomplete:`off`}),r=F(`p`,{class:`broker-error`,role:`alert`});for(;;){if(!await y(A(`ownerTitle`),[F(`p`,{},A(`ownerIntro`)),F(`p`,{},F(`a`,{href:t.tokenLink.url,target:`_blank`,rel:`noreferrer`},A(`ownerCreate`))),F(`label`,{for:`broker-owner-token`},A(`ownerLabel`)),n,r],[{label:A(`cancel`),value:!1},{label:A(`ownerUse`),value:!0,primary:!0}]))throw new l(`declined`,A(`declined`));try{await t.applyToken(n.value.trim());return}catch(e){r.textContent=A(`signInError`,{message:I(e)})}}}async function S(e){let t=R(),n=new Map,r=P.map(e=>{let r=F(`input`,{type:`password`,id:`broker-ai-${e}`,autocomplete:`off`}),i=t[e];return typeof i==`string`&&(r.value=i),n.set(e,r),F(`div`,{},F(`label`,{for:`broker-ai-${e}`},_[e].name),r)}),i=F(`input`,{type:`checkbox`,id:`broker-ai-remember`});if(i.checked=localStorage.getItem(M)!==null,!await y(A(`aiTitle`),[F(`p`,{},A(`aiIntro`)),...r,F(`label`,{class:`broker-check`},i,` ${A(`aiRemember`)}`)],[{label:A(`cancel`),value:!1},{label:A(`aiSave`),value:!0,primary:!0}]))return;let a={};for(let[e,t]of n)t.value.trim()&&(a[e]=t.value.trim());z(a,i.checked),e()}}await H({root:document.getElementById(`broker`),config:await fetch(`./broker.json`,{cache:`no-store`}).then(e=>e.ok?e.json():void 0).catch(()=>void 0),hosts:{"@goodfellow-cms/github":()=>t(()=>import(`./dist-C20K9oCc.js`),__vite__mapDeps([0,1,2,3,4]),import.meta.url),"@goodfellow-cms/gitlab":()=>t(()=>import(`./dist-cedgnWG_.js`),__vite__mapDeps([5,1,2,3]),import.meta.url)}});
@@ -1,5 +0,0 @@
1
- import{a as e,o as t}from"./store-5raQS3us.js";var n=class extends Error{problem;name=`DomainError`;constructor(e,t){super(t),this.problem=e}},r=`goodfellow-draft-`,i=/^[a-z0-9][a-z0-9-]{0,39}$/;function a(e){return i.test(e)}var o=class extends Error{name=`DraftError`;problem;constructor(e,t){super(t),this.problem=e}};function s(e){if(!a(e))throw new o(`not-found`,`"${e}" isn't a draft's name.`);return`${r}${e}`}function c(t,n){function i(r,i){let a=n.branchStore(i);async function o(){let e=await n.mergeBase(i);return a.changedPaths(e,await a.revision())}async function s(){let e=[];for(let t of await o())if(t.startsWith(`public/media/`)){let n=await a.readBytes(t);e.push(n?{path:t,bytes:n}:{path:t,delete:!0})}else{let n=await a.read(t);e.push(n===void 0?{path:t,delete:!0}:{path:t,content:n})}return e}return{name:r,store:a,changes:s,paths:o,async publish(r){let a=await n.mergeBase(i),o=await s(),c=o.length>0?await e(t,o,{message:r,expectedRevision:a}):{revision:await t.revision()};return await n.deleteBranch(i),c},async submitForReview({title:e,description:t=``}){return n.openReview({branch:i,title:e,description:t})},async discard(){await n.deleteBranch(i)}}}return{async create(e,r){let a=s(e);return await n.createBranch(a,r?.from??await t.revision()),i(e,a)},async open(e){let t=s(e);return await n.mergeBase(t),i(e,t)},async list(){return(await n.listBranches(r)).map(e=>e.slice(17)).filter(a).sort().reverse()}}}var l=class extends Error{problem;name=`EditorsError`;constructor(e,t){super(t),this.problem=e}};function u(e){let t=/^[\^~=v]*(\d+)\.(\d+)\.(\d+)$/.exec(e.trim());return t?[Number(t[1]),Number(t[2]),Number(t[3])]:void 0}function d(e,t){return e[0]-t[0]||e[1]-t[1]||e[2]-t[2]}function f(e,t){let n=u(e),r=u(t);return n&&r?d(n,r):0}function p(e){return u(e)?.join(`.`)}function m(e){try{let{dependencies:t={},devDependencies:n={}}=JSON.parse(e),r=t[`@goodfellow-cms/react`]??n[`@goodfellow-cms/react`];return r?p(r):void 0}catch{return}}var h=`goodfellow-update `;function g(e){let t=e.split(`
2
- `);for(let e=t.length-1;e>=0;e--){let n=t[e]??``,r=n.indexOf(h);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 _=`GOODFELLOW_NIGHTLY`,v=[`changed`,`always`,`off`];function y(e){let t=e?.trim().toLowerCase();return v.includes(t)?t:`changed`}var b=class extends Error{problem;name=`UpdatesError`;constructor(e,t){super(t),this.problem=e}},x=`goodfellow-build-problem `;function S(e){let t=e.split(`
3
- `);for(let e=t.length-1;e>=0;e--){let n=t[e]??``,r=n.indexOf(x);if(r!==-1)try{let e=JSON.parse(n.slice(r+25).trim());if((e.kind===`content`||e.kind===`code`)&&typeof e.message==`string`)return{kind:e.kind,message:e.message,...typeof e.file==`string`&&e.file&&{file:e.file}}}catch{}}}function C(e){let t=e.toLowerCase();if(/deploy-pages|deploy to |pages:deploy/.test(t))return`deploy`;if(/configure-pages|upload-pages-artifact|setup pages|set up pages/.test(t))return`pages`;if(/\b(npm (ci|install)|pnpm install|yarn( install)?|install packages)\b/.test(t))return`install`;if(/\bbuild\b/.test(t))return`build`}var w=`rebuild`;`${w}`;function T(e,t=`# `){let n=[];for(let r of e.split(`
4
- `)){let e=``;for(let i of r.split(` `))e&&e.length+i.length+1>78-t.length?(n.push(e),e=i):e=e?`${e} ${i}`:i;n.push(e)}return n.map(e=>`${t}${e}`.trimEnd()).join(`
5
- `)}`${T(`Drafts, from the admin panel's Add to draft and from Claude, are kept on branches named goodfellow-draft-…, which visitors never see, so Vercel doesn't build previews of them.`,` // `)}`,T(`The admin address's header rules, from the code's goodfellow.config.tsx: goodfellow admin and goodfellow broker, run in the code's folder, copy them here, since Vercel reads this file before the code is cloned.`,` // `),`${t}${t}`;var E=class extends Error{problem;link;name=`SetupError`;constructor(e,t,n){super(t),this.problem=e,this.link=n}};export{_ as a,g as c,l as d,o as f,S as i,y as l,n as m,w as n,b as o,c as p,C as r,f as s,E as t,m as u};
@@ -1 +0,0 @@
1
- var e=`content`,t=`public/media`,n=`blocks/installed`,r=`components`,i=`hooks`,a=`content-repository`,o=class extends Error{name=`ConflictError`;constructor(e=`The site changed since it was loaded.`){super(e)}},s=[e,t,n,r,`lib`,i];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 l(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 o)||!e.changedPaths||a===2)throw t;let s=await e.revision();if(s===r||(await e.changedPaths(n.expectedRevision,s)).some(e=>i.has(e)))throw t;r=s}}var u=[e,t];function d(e){return c(e)&&u.some(t=>e.startsWith(`${t}/`))}var f=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 p(e){let t=e.find(e=>!d(e.path));if(t)throw new f(t.path)}export{l as a,d as i,s as n,a as o,p as r,o as t};