drupflare/worker - v1.0.4
    Preparing search index...

    Variable ADMIN_GIT_JSConst

    ADMIN_GIT_JS: "const out = document.getElementById('git-out');\nconst detail = document.getElementById('git-detail');\nfunction esc(s) {\n\tconst d = document.createElement('span');\n\td.textContent = String(s == null ? '' : s);\n\treturn d.innerHTML;\n}\n// the session cookie rides on a same-origin fetch, so nothing here holds the token\nasync function call(params) {\n\tconst res = await fetch('/git?' + new URLSearchParams(params), { credentials: 'same-origin' });\n\tif (res.status === 401) {\n\t\twindow.location.href = '__CFW_LOGIN_PATH__?next=' + encodeURIComponent(location.pathname);\n\t\treturn;\n\t}\n\tconst data = await res.json();\n\tif (!data.ok) throw new Error(data.error || 'refused');\n\treturn data;\n}\nfunction showChanges(data) {\n\tconst c = data.counts || {};\n\tconst head =\n\t\t'<h2>' +\n\t\tesc(String(data.sha || '').slice(0, 12)) +\n\t\t'</h2>' +\n\t\t'<p class=\"sub\">+' +\n\t\t(c.added || 0) +\n\t\t' added, ~' +\n\t\t(c.modified || 0) +\n\t\t' modified, -' +\n\t\t(c.removed || 0) +\n\t\t' removed, ' +\n\t\t(c.unchanged || 0) +\n\t\t' unchanged. ' +\n\t\t(data.rowsWritten || 0) +\n\t\t' rows would be written.</p>';\n\tconst conflicts = (data.conflicts || []).length\n\t\t? '<p class=\"sub\"><strong>' +\n\t\t\tdata.conflicts.length +\n\t\t\t' conflicting path(s):</strong> ' +\n\t\t\tdata.conflicts\n\t\t\t\t.map(function (x) {\n\t\t\t\t\treturn esc(x.path) + ' (owned by ' + esc(x.owner) + ')';\n\t\t\t\t})\n\t\t\t\t.join(', ') +\n\t\t\t'</p>'\n\t\t: '';\n\tconst mods = (data.modules || []).length\n\t\t? '<p class=\"sub\">Modules: ' +\n\t\t\tdata.modules\n\t\t\t\t.map(function (m) {\n\t\t\t\t\treturn '<code>' + esc(m.name) + '</code> (' + esc(m.type) + ')';\n\t\t\t\t})\n\t\t\t\t.join(', ') +\n\t\t\t'</p>'\n\t\t: '';\n\tconst rows = (data.changes || [])\n\t\t.filter(function (ch) {\n\t\t\treturn ch.kind !== 'unchanged';\n\t\t})\n\t\t.map(function (ch) {\n\t\t\treturn (\n\t\t\t\t'<tr><td><code>' +\n\t\t\t\tesc(ch.path) +\n\t\t\t\t'</code></td><td>' +\n\t\t\t\tesc(ch.kind) +\n\t\t\t\t'</td>' +\n\t\t\t\t'<td class=\"dim\">+' +\n\t\t\t\t(ch.added || 0) +\n\t\t\t\t' / -' +\n\t\t\t\t(ch.removed || 0) +\n\t\t\t\t'</td></tr>'\n\t\t\t);\n\t\t})\n\t\t.join('');\n\tdetail.innerHTML =\n\t\t'<div class=\"card\">' +\n\t\thead +\n\t\tmods +\n\t\tconflicts +\n\t\t(rows\n\t\t\t? '<table><thead><tr><th>File</th><th>Change</th><th>Lines</th></tr></thead><tbody>' +\n\t\t\t\trows +\n\t\t\t\t'</tbody></table>'\n\t\t\t: '<p class=\"sub\">No file differs.</p>') +\n\t\t'</div>';\n}\nfunction showPulls(data, id) {\n\tconst rows = (data.pulls || [])\n\t\t.map(function (p) {\n\t\t\treturn (\n\t\t\t\t'<tr><td>#' +\n\t\t\t\tesc(p.id) +\n\t\t\t\t'</td><td>' +\n\t\t\t\tesc(p.title) +\n\t\t\t\t'</td><td><code>' +\n\t\t\t\tesc(p.branch) +\n\t\t\t\t'</code> &rarr; <code>' +\n\t\t\t\tesc(p.target) +\n\t\t\t\t'</code></td><td>' +\n\t\t\t\tesc(p.author) +\n\t\t\t\t(p.draft ? ' <em>draft</em>' : '') +\n\t\t\t\t'</td><td><button data-preview=\"' +\n\t\t\t\tesc(p.id) +\n\t\t\t\t'\" data-id=\"' +\n\t\t\t\tesc(id) +\n\t\t\t\t'\">Preview</button></td></tr>'\n\t\t\t);\n\t\t})\n\t\t.join('');\n\tdetail.innerHTML =\n\t\t'<div class=\"card\"><h2>Open Requests</h2>' +\n\t\t(rows\n\t\t\t? '<table><thead><tr><th>#</th><th>Title</th><th>Branch</th><th>Author</th><th></th></tr></thead><tbody>' +\n\t\t\t\trows +\n\t\t\t\t'</tbody></table>'\n\t\t\t: '<p class=\"sub\">Nothing open.</p>') +\n\t\t'<p class=\"sub\">A preview installs that request\\'s head instead of the branch. Polling and pushes are held until you leave it.</p></div>';\n\tdetail.querySelectorAll('button[data-preview]').forEach(function (b) {\n\t\tb.addEventListener('click', async function () {\n\t\t\tout.textContent = 'Previewing #' + b.dataset.preview + '...';\n\t\t\ttry {\n\t\t\t\tconst res = await call({\n\t\t\t\t\taction: 'preview',\n\t\t\t\t\tid: b.dataset.id,\n\t\t\t\t\tpr: b.dataset.preview\n\t\t\t\t});\n\t\t\t\tout.textContent = 'Previewing #' + b.dataset.preview + '.';\n\t\t\t\tshowChanges(res);\n\t\t\t} catch (err) {\n\t\t\t\tout.textContent = 'Failed: ' + err.message;\n\t\t\t}\n\t\t});\n\t});\n}\ndocument.getElementById('git-add').addEventListener('submit', async (e) => {\n\te.preventDefault();\n\tconst f = new FormData(e.target);\n\tif (!f.get('repo')) {\n\t\tout.textContent = 'A repository is needed.';\n\t\treturn;\n\t}\n\tif (!f.get('token') && f.get('provider') !== 'generic') {\n\t\tout.textContent = 'That provider needs an access token.';\n\t\treturn;\n\t}\n\tout.textContent = 'Connecting...';\n\ttry {\n\t\tconst data = await call({\n\t\t\taction: 'add',\n\t\t\tprovider: f.get('provider'),\n\t\t\trepo: f.get('repo'),\n\t\t\tbranch: f.get('branch') || '',\n\t\t\ttoken: f.get('token') || '',\n\t\t\temail: f.get('email') || '',\n\t\t\tusername: f.get('username') || '',\n\t\t\tinterval: f.get('interval') || '60'\n\t\t});\n\t\tout.textContent = 'Connected ' + data.repo + ' at ' + (data.head || 'unknown') + '.';\n\t\twindow.location.reload();\n\t} catch (err) {\n\t\tout.textContent = 'Could not connect: ' + err.message;\n\t}\n});\ndocument.querySelectorAll('select[data-branch]').forEach((s) => {\n\ts.addEventListener('focus', async () => {\n\t\tif (s.dataset.loaded) return;\n\t\ttry {\n\t\t\tconst data = await call({ action: 'branches', id: s.dataset.branch });\n\t\t\ts.dataset.loaded = '1';\n\t\t\tdata.branches.forEach(function (b) {\n\t\t\t\tconst o = document.createElement('option');\n\t\t\t\to.value = b;\n\t\t\t\to.textContent = b + (b === data.current ? ' (current)' : '');\n\t\t\t\ts.appendChild(o);\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tout.textContent = 'Could not list branches: ' + err.message;\n\t\t}\n\t});\n\ts.addEventListener('change', async () => {\n\t\tif (!s.value) return;\n\t\tout.textContent = 'Switching to ' + s.value + '...';\n\t\ttry {\n\t\t\tconst data = await call({ action: 'switch', id: s.dataset.branch, branch: s.value });\n\t\t\tshowChanges(data);\n\t\t\twindow.location.reload();\n\t\t} catch (err) {\n\t\t\tout.textContent = 'Could not switch: ' + err.message;\n\t\t}\n\t});\n});\ndocument.querySelectorAll('input[data-interval]').forEach((i) => {\n\ti.addEventListener('change', async () => {\n\t\ttry {\n\t\t\tconst data = await call({\n\t\t\t\taction: 'interval',\n\t\t\t\tid: i.dataset.interval,\n\t\t\t\tminutes: i.value\n\t\t\t});\n\t\t\tout.textContent = data.message;\n\t\t} catch (err) {\n\t\t\tout.textContent = 'Failed: ' + err.message;\n\t\t}\n\t});\n});\ndocument.querySelectorAll('button[data-act]').forEach((b) => {\n\tb.addEventListener('click', async () => {\n\t\tif (\n\t\t\tb.dataset.act === 'remove' &&\n\t\t\t!window.confirm('Disconnect ' + b.dataset.id + '? Its files stay installed.')\n\t\t)\n\t\t\treturn;\n\t\tout.textContent = b.dataset.act + '...';\n\t\ttry {\n\t\t\t// A PLAIN REMOTE HAS NO API TO REGISTER A HOOK THROUGH, and this page told the operator\n\t\t\t// to press this button anyway: action=hook is refused with 400 for a non-API provider,\n\t\t\t// and hooksecret -- the manual path the prose describes -- had no caller anywhere.\n\t\t\tconst action =\n\t\t\t\tb.dataset.act === 'hook' && b.dataset.provider === 'generic'\n\t\t\t\t\t? 'hooksecret'\n\t\t\t\t\t: b.dataset.act;\n\t\t\tconst data = await call({ action, id: b.dataset.id });\n\t\t\tif (\n\t\t\t\tb.dataset.act === 'diff' ||\n\t\t\t\tb.dataset.act === 'pull' ||\n\t\t\t\tb.dataset.act === 'unpreview'\n\t\t\t) {\n\t\t\t\tshowChanges(data);\n\t\t\t\tout.textContent = data.applied === false && data.rolledBack ? data.error : 'done';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (b.dataset.act === 'prs') {\n\t\t\t\tshowPulls(data, b.dataset.id);\n\t\t\t\tout.textContent = 'done';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (b.dataset.act === 'hook') {\n\t\t\t\tout.textContent = data.secret\n\t\t\t\t\t? 'Add this delivery URL and secret to your host. URL: ' +\n\t\t\t\t\t\tdata.deliverTo +\n\t\t\t\t\t\t' Secret: ' +\n\t\t\t\t\t\tdata.secret\n\t\t\t\t\t: data.message + ' Delivery URL: ' + data.deliverTo;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tout.textContent = data.message || 'done';\n\t\t\tif (b.dataset.act === 'remove') window.location.reload();\n\t\t} catch (err) {\n\t\t\tout.textContent = 'Failed: ' + err.message;\n\t\t}\n\t});\n});\n"