@cloud-cli/on 1.45.1 → 1.45.2

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.
Files changed (2) hide show
  1. package/dist/on.js +1 -1
  2. package/package.json +1 -1
package/dist/on.js CHANGED
@@ -6247,7 +6247,7 @@ var Hi = {
6247
6247
  let t = await C.run("UPDATE api_keys SET revoked_at = CURRENT_TIMESTAMP WHERE id = ? AND revoked_at IS NULL", [e]);
6248
6248
  return Number(t?.changes || 0) > 0;
6249
6249
  }
6250
- }, Gi = "<!doctype html>\n<html lang=\"en\" class=\"dark\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Runner settings</title>\n <script type=\"importmap\">\n { \"imports\": { \"@li3/\": \"https://cdn.li3.dev/@li3/\" } }\n <\/script>\n <link rel=\"component\" href=\"https://sodium.static.apphor.de/lucide-icon.html\" />\n <link rel=\"component\" href=\"/app-header.html\" />\n </head>\n <body data-page=\"__SETTINGS_PAGE__\" class=\"min-h-screen bg-gray-950 p-4 font-sans text-gray-100 md:p-6\">\n <template app>\n <main class=\"mx-auto max-w-6xl space-y-5\">\n <app-header title=\"Settings\" subtitle=\"Human-admin controls and automation credentials\" back=\"/runs\" back-label=\"Back to jobs\"></app-header>\n <nav class=\"flex flex-wrap gap-1 rounded-xl border border-gray-800 bg-gray-900/70 p-1\" aria-label=\"Settings navigation\">\n <a href=\"/settings/workflows\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Workflows</a>\n <a href=\"/settings/secrets\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Secrets</a>\n <a href=\"/settings/tokens\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">API tokens</a>\n <a href=\"/settings/notifications\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Notifications</a>\n </nav>\n\n <template if=\"page === 'tokens'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\">\n <h2 class=\"text-lg font-semibold text-white\">Profile</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Authenticated as the human administrator.</p>\n </section>\n </template>\n <template if=\"page === 'notifications'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"notifications-title\">\n <h2 id=\"notifications-title\" class=\"text-lg font-semibold text-white\">Notifications</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Receive job completion notifications on this device.</p>\n <button type=\"button\" on-click=\"toggleNotifications()\" class=\"mt-5 inline-flex items-center gap-2 rounded-lg border border-indigo-500/60 px-4 py-2.5 text-sm font-medium text-indigo-200 outline-none hover:bg-indigo-500/10 focus-visible:ring-2 focus-visible:ring-indigo-400/60\">\n <lucide-icon bind-icon=\"notificationsEnabled ? 'bell-off' : 'bell-ring'\" size=\"16\"></lucide-icon>\n {{ notificationsEnabled ? 'Disable notifications' : 'Enable notifications' }}\n </button>\n <p class=\"mt-3 text-sm text-gray-400\" role=\"status\">{{ notificationMessage }}</p>\n </section>\n </template>\n\n <template if=\"page === 'tokens'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"keys-title\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <h2 id=\"keys-title\" class=\"text-lg font-semibold text-white\">API keys</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Issue narrowly scoped credentials for automation tools. Keys are shown only once.</p>\n </div>\n </div>\n <div class=\"mt-5 grid gap-3 rounded-xl border border-gray-800 bg-gray-950/50 p-4 md:grid-cols-[1fr_auto]\">\n <label class=\"sr-only\" for=\"key-name\">Key name</label>\n <input id=\"key-name\" bind-value=\"keyName\" on-input=\"setKeyName($event)\" placeholder=\"Documentation bot\" class=\"rounded-lg border border-gray-700 bg-gray-900 px-3 py-2.5 text-sm outline-none focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/30\" />\n <button type=\"button\" on-click=\"issueKey()\" class=\"inline-flex items-center justify-center gap-2 rounded-lg bg-indigo-500 px-4 py-2.5 text-sm font-semibold text-white outline-none hover:bg-indigo-400 focus-visible:ring-2 focus-visible:ring-indigo-400/60\"><lucide-icon icon=\"key-round\" size=\"16\"></lucide-icon>Issue key</button>\n <fieldset class=\"md:col-span-2\">\n <legend class=\"mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500\">Scopes</legend>\n <div class=\"space-y-2\">\n <template for=\"scope of scopeOptions\">\n <label class=\"group flex cursor-pointer items-center gap-3 text-sm text-gray-300\">\n <input type=\"checkbox\" bind-checked=\"scope.selected\" on-change=\"toggleScope(scope)\" class=\"peer sr-only\" />\n <span aria-hidden=\"true\" class=\"flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-gray-600 bg-gray-900 text-transparent transition peer-checked:border-indigo-400 peer-checked:bg-indigo-500 peer-checked:text-white peer-focus-visible:ring-2 peer-focus-visible:ring-indigo-400/70 peer-disabled:opacity-50\">\n <svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m3 8 3 3 7-7\"></path></svg>\n </span>\n <span class=\"group-hover:text-white\">{{ scope.label }}</span>\n </label>\n </template>\n </div>\n </fieldset>\n </div>\n <template if=\"newToken\">\n <div class=\"mt-4 rounded-xl border border-amber-500/40 bg-amber-500/10 p-4\" role=\"alert\">\n <p class=\"text-sm font-semibold text-amber-200\">Copy this key now. It cannot be shown again.</p>\n <code class=\"mt-2 block select-all break-all rounded bg-gray-950 p-3 font-mono text-xs text-amber-100\">{{ newToken }}</code>\n </div>\n </template>\n <ul class=\"mt-5 divide-y divide-gray-800\" aria-label=\"Active API keys\">\n <template for=\"key of keys\">\n <li class=\"flex items-center justify-between gap-3 py-3\">\n <div class=\"min-w-0\"><p class=\"truncate text-sm font-medium text-gray-200\">{{ key.name }}</p><p class=\"text-xs text-gray-500\">{{ key.scopes.join(', ') }} · created {{ key.created_at }}</p></div>\n <button type=\"button\" on-click=\"revokeKey(key)\" class=\"shrink-0 rounded-lg p-2 text-rose-300 outline-none hover:bg-rose-500/10 focus-visible:ring-2 focus-visible:ring-rose-400/60\" aria-label=\"Revoke {{ key.name }}\" title=\"Revoke key\"><lucide-icon icon=\"trash\" size=\"16\"></lucide-icon></button>\n </li>\n </template>\n </ul>\n </section>\n </template>\n <p class=\"text-sm text-rose-300\" role=\"alert\" class-hidden=\"!error\">{{ error }}</p>\n </main>\n <script setup>\n import { onInit, ref } from '@li3/web';\n export default function () {\n const page = document.body.dataset.page;\n const keys = ref([]);\n const keyName = ref('');\n const newToken = ref('');\n const error = ref('');\n const notificationsSupported = ref('Notification' in window && 'serviceWorker' in navigator);\n const notificationsEnabled = ref(notificationsSupported.value && Notification.permission === 'granted' && localStorage.getItem('runner-notifications') === 'enabled');\n const notificationMessage = ref('');\n const scopeOptions = ref([\n { name: 'workflows:read', label: 'Read workflows', selected: true },\n { name: 'workflows:write', label: 'Modify workflows', selected: false },\n { name: 'logs:read', label: 'Read logs', selected: false },\n { name: 'artifacts:read', label: 'Read artifacts', selected: false },\n { name: 'runs:control', label: 'Control runs', selected: false },\n ]);\n const api = async (url, options = {}) => { const response = await fetch(url, { headers: { accept: 'application/json', ...(options.body ? { 'content-type': 'application/json' } : {}) }, ...options }); const body = await response.json().catch(() => ({})); if (!response.ok) throw new Error(body.error || `Request failed: ${response.status}`); return body; };\n const load = async () => { keys.value = (await api('/api/api-keys')).keys; };\n const issueKey = async () => { try { error.value = ''; const result = await api('/api/api-keys', { method: 'POST', body: JSON.stringify({ name: keyName.value, scopes: scopeOptions.value.filter((scope) => scope.selected).map((scope) => scope.name) }) }); newToken.value = result.token; keyName.value = ''; await load(); } catch (reason) { error.value = reason.message; } };\n const revokeKey = async (key) => { if (!confirm(`Revoke ${key.name}?`)) return; try { await api(`/api/api-keys/${key.id}`, { method: 'DELETE' }); await load(); } catch (reason) { error.value = reason.message; } };\n const setKeyName = (event) => { keyName.value = event.target.value; };\n const toggleScope = (scope) => { scope.selected = !scope.selected; };\n const toggleNotifications = async () => {\n if (notificationsEnabled.value) {\n notificationsEnabled.value = false;\n localStorage.removeItem('runner-notifications');\n notificationMessage.value = 'Notifications disabled on this device.';\n return;\n }\n if (!notificationsSupported.value) { notificationMessage.value = 'Notifications are not supported by this browser.'; return; }\n const permission = await Notification.requestPermission();\n notificationsEnabled.value = permission === 'granted';\n if (notificationsEnabled.value) { localStorage.setItem('runner-notifications', 'enabled'); notificationMessage.value = 'Notifications enabled.'; }\n else notificationMessage.value = 'Notification permission was not granted.';\n };\n onInit(() => { if (page === 'tokens') load().catch((reason) => { error.value = reason.message; }); });\n return { page, keys, keyName, newToken, error, scopeOptions, issueKey, revokeKey, setKeyName, toggleScope, notificationsEnabled, notificationMessage, toggleNotifications };\n }\n <\/script>\n </template>\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n </body>\n</html>\n";
6250
+ }, Gi = "<!doctype html>\n<html lang=\"en\" class=\"dark\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Runner settings</title>\n <script type=\"importmap\">\n { \"imports\": { \"@li3/\": \"https://cdn.li3.dev/@li3/\" } }\n <\/script>\n <link rel=\"component\" href=\"https://sodium.static.apphor.de/lucide-icon.html\" />\n <link rel=\"component\" href=\"/app-header.html\" />\n </head>\n <body data-page=\"__SETTINGS_PAGE__\" class=\"min-h-screen bg-gray-950 p-4 font-sans text-gray-100 md:p-6\">\n <template app>\n <main class=\"mx-auto max-w-6xl space-y-5\">\n <app-header title=\"Settings\" subtitle=\"Human-admin controls and automation credentials\" back=\"/runs\" back-label=\"Back to jobs\"></app-header>\n <nav class=\"flex flex-wrap gap-1 rounded-xl border border-gray-800 bg-gray-900/70 p-1\" aria-label=\"Settings navigation\">\n <a href=\"/settings/workflows\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Workflows</a>\n <a href=\"/settings/secrets\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Secrets</a>\n <a href=\"/settings/tokens\" bind-class=\"page === 'tokens' ? 'bg-gray-800.text-white' : ''\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">API tokens</a>\n <a href=\"/settings/notifications\" bind-class=\"page === 'notifications' ? 'bg-gray-800.text-white' : ''\" class=\"rounded-lg px-3 py-2 text-sm text-gray-300 hover:bg-gray-800\">Notifications</a>\n </nav>\n\n <template if=\"page === 'tokens'\">\n </template>\n <template if=\"page === 'notifications'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"notifications-title\">\n <h2 id=\"notifications-title\" class=\"text-lg font-semibold text-white\">Notifications</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Receive job completion notifications on this device.</p>\n <button type=\"button\" on-click=\"toggleNotifications()\" class=\"mt-5 inline-flex items-center gap-2 rounded-lg border border-indigo-500/60 px-4 py-2.5 text-sm font-medium text-indigo-200 outline-none hover:bg-indigo-500/10 focus-visible:ring-2 focus-visible:ring-indigo-400/60\">\n <lucide-icon bind-icon=\"notificationsEnabled ? 'bell-off' : 'bell-ring'\" size=\"16\"></lucide-icon>\n {{ notificationsEnabled ? 'Disable notifications' : 'Enable notifications' }}\n </button>\n <p class=\"mt-3 text-sm text-gray-400\" role=\"status\">{{ notificationMessage }}</p>\n </section>\n </template>\n\n <template if=\"page === 'tokens'\">\n <section class=\"rounded-2xl border border-gray-800 bg-gray-900/80 p-5\" aria-labelledby=\"keys-title\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <h2 id=\"keys-title\" class=\"text-lg font-semibold text-white\">API keys</h2>\n <p class=\"mt-1 text-sm text-gray-400\">Issue narrowly scoped credentials for automation tools. Keys are shown only once.</p>\n </div>\n </div>\n <div class=\"mt-5 grid gap-3 rounded-xl border border-gray-800 bg-gray-950/50 p-4 md:grid-cols-[1fr_auto]\">\n <label class=\"sr-only\" for=\"key-name\">Key name</label>\n <input id=\"key-name\" bind-value=\"keyName\" on-input=\"setKeyName($event)\" placeholder=\"Documentation bot\" class=\"rounded-lg border border-gray-700 bg-gray-900 px-3 py-2.5 text-sm outline-none focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/30\" />\n <button type=\"button\" on-click=\"issueKey()\" class=\"inline-flex items-center justify-center gap-2 rounded-lg bg-indigo-500 px-4 py-2.5 text-sm font-semibold text-white outline-none hover:bg-indigo-400 focus-visible:ring-2 focus-visible:ring-indigo-400/60\"><lucide-icon icon=\"key-round\" size=\"16\"></lucide-icon>Issue key</button>\n <fieldset class=\"md:col-span-2\">\n <legend class=\"mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500\">Scopes</legend>\n <div class=\"space-y-2\">\n <template for=\"scope of scopeOptions\">\n <label class=\"group flex cursor-pointer items-center gap-3 text-sm text-gray-300\">\n <input type=\"checkbox\" bind-checked=\"scope.selected\" on-change=\"toggleScope(scope)\" class=\"peer sr-only\" />\n <span aria-hidden=\"true\" class=\"flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-gray-600 bg-gray-900 text-transparent transition peer-checked:border-indigo-400 peer-checked:bg-indigo-500 peer-checked:text-white peer-focus-visible:ring-2 peer-focus-visible:ring-indigo-400/70 peer-disabled:opacity-50\">\n <svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m3 8 3 3 7-7\"></path></svg>\n </span>\n <span class=\"group-hover:text-white\">{{ scope.label }}</span>\n </label>\n </template>\n </div>\n </fieldset>\n </div>\n <template if=\"newToken\">\n <div class=\"mt-4 rounded-xl border border-amber-500/40 bg-amber-500/10 p-4\" role=\"alert\">\n <p class=\"text-sm font-semibold text-amber-200\">Copy this key now. It cannot be shown again.</p>\n <code class=\"mt-2 block select-all break-all rounded bg-gray-950 p-3 font-mono text-xs text-amber-100\">{{ newToken }}</code>\n </div>\n </template>\n <h3 class=\"mt-5 text-xs font-semibold uppercase tracking-wider text-gray-500\">Active tokens</h3>\n <ul class=\"mt-2 space-y-2\" aria-label=\"Active API keys\">\n <template for=\"key of keys\">\n <li class=\"flex items-center justify-between gap-3 rounded-xl border border-gray-800 bg-gray-950/60 px-4 py-3\">\n <div class=\"min-w-0\"><p class=\"truncate text-sm font-medium text-gray-200\">{{ key.name }}</p><p class=\"text-xs text-gray-500\">{{ key.scopes.join(', ') }} · created {{ key.created_at }}</p></div>\n <button type=\"button\" on-click=\"revokeKey(key)\" class=\"shrink-0 rounded-lg p-2 text-rose-300 outline-none hover:bg-rose-500/10 focus-visible:ring-2 focus-visible:ring-rose-400/60\" aria-label=\"Revoke {{ key.name }}\" title=\"Revoke key\"><lucide-icon icon=\"trash\" size=\"16\"></lucide-icon></button>\n </li>\n </template>\n </ul>\n </section>\n </template>\n <p class=\"text-sm text-rose-300\" role=\"alert\" class-hidden=\"!error\">{{ error }}</p>\n </main>\n <script setup>\n import { onInit, ref } from '@li3/web';\n export default function () {\n const page = document.body.dataset.page;\n const keys = ref([]);\n const keyName = ref('');\n const newToken = ref('');\n const error = ref('');\n const notificationsSupported = ref('Notification' in window && 'serviceWorker' in navigator);\n const notificationsEnabled = ref(notificationsSupported.value && Notification.permission === 'granted' && localStorage.getItem('runner-notifications') === 'enabled');\n const notificationMessage = ref('');\n const scopeOptions = ref([\n { name: 'workflows:read', label: 'Read workflows', selected: true },\n { name: 'workflows:write', label: 'Modify workflows', selected: false },\n { name: 'logs:read', label: 'Read logs', selected: false },\n { name: 'artifacts:read', label: 'Read artifacts', selected: false },\n { name: 'runs:control', label: 'Control runs', selected: false },\n ]);\n const api = async (url, options = {}) => { const response = await fetch(url, { headers: { accept: 'application/json', ...(options.body ? { 'content-type': 'application/json' } : {}) }, ...options }); const body = await response.json().catch(() => ({})); if (!response.ok) throw new Error(body.error || `Request failed: ${response.status}`); return body; };\n const load = async () => { keys.value = (await api('/api/api-keys')).keys; };\n const issueKey = async () => { try { error.value = ''; const result = await api('/api/api-keys', { method: 'POST', body: JSON.stringify({ name: keyName.value, scopes: scopeOptions.value.filter((scope) => scope.selected).map((scope) => scope.name) }) }); newToken.value = result.token; keyName.value = ''; await load(); } catch (reason) { error.value = reason.message; } };\n const revokeKey = async (key) => { if (!confirm(`Revoke ${key.name}?`)) return; try { await api(`/api/api-keys/${key.id}`, { method: 'DELETE' }); await load(); } catch (reason) { error.value = reason.message; } };\n const setKeyName = (event) => { keyName.value = event.target.value; };\n const toggleScope = (scope) => { scope.selected = !scope.selected; };\n const toggleNotifications = async () => {\n if (notificationsEnabled.value) {\n notificationsEnabled.value = false;\n localStorage.removeItem('runner-notifications');\n notificationMessage.value = 'Notifications disabled on this device.';\n return;\n }\n if (!notificationsSupported.value) { notificationMessage.value = 'Notifications are not supported by this browser.'; return; }\n const permission = await Notification.requestPermission();\n notificationsEnabled.value = permission === 'granted';\n if (notificationsEnabled.value) { localStorage.setItem('runner-notifications', 'enabled'); notificationMessage.value = 'Notifications enabled.'; }\n else notificationMessage.value = 'Notification permission was not granted.';\n };\n onInit(() => { if (page === 'tokens') load().catch((reason) => { error.value = reason.message; }); });\n return { page, keys, keyName, newToken, error, scopeOptions, issueKey, revokeKey, setKeyName, toggleScope, notificationsEnabled, notificationMessage, toggleNotifications };\n }\n <\/script>\n </template>\n <script type=\"module\">import '@li3/web';<\/script>\n <script src=\"https://cdn.tailwindcss.com\"><\/script>\n </body>\n</html>\n";
6251
6251
  //#endregion
6252
6252
  //#region src/settings-ui.ts
6253
6253
  function Ki(e = "tokens") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloud-cli/on",
3
- "version": "1.45.1",
3
+ "version": "1.45.2",
4
4
  "description": "CLI entry point for the on plugin ecosystem.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@12.3.4",