@samyx/preview-stacks-ui-hearth 0.0.0-stage → 0.43.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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -2
  3. package/dist/assets/ConfigView-DdEhTo0d.css +1 -0
  4. package/dist/assets/ConfigView-nQLAHdV-.js +4 -0
  5. package/dist/assets/ConfigView-nQLAHdV-.js.map +1 -0
  6. package/dist/assets/ControlView-Cg4SUV8Q.js +2 -0
  7. package/dist/assets/ControlView-Cg4SUV8Q.js.map +1 -0
  8. package/dist/assets/ControlView-gcpfs_0z.css +1 -0
  9. package/dist/assets/DeploymentView-C4h3spUV.css +32 -0
  10. package/dist/assets/DeploymentView-D_wV0QNw.js +4 -0
  11. package/dist/assets/DeploymentView-D_wV0QNw.js.map +1 -0
  12. package/dist/assets/DeploymentsView-Be8tO0RI.js +2 -0
  13. package/dist/assets/DeploymentsView-Be8tO0RI.js.map +1 -0
  14. package/dist/assets/JobView-DL9KQcjx.js +2 -0
  15. package/dist/assets/JobView-DL9KQcjx.js.map +1 -0
  16. package/dist/assets/JobsView-Bq4PtEaW.js +2 -0
  17. package/dist/assets/JobsView-Bq4PtEaW.js.map +1 -0
  18. package/dist/assets/NotFoundView-BKHjS8HU.js +2 -0
  19. package/dist/assets/NotFoundView-BKHjS8HU.js.map +1 -0
  20. package/dist/assets/NotifiersView-D5vKpsLv.js +2 -0
  21. package/dist/assets/NotifiersView-D5vKpsLv.js.map +1 -0
  22. package/dist/assets/OverviewView-B1-3hrnt.js +2 -0
  23. package/dist/assets/OverviewView-B1-3hrnt.js.map +1 -0
  24. package/dist/assets/PublicLogsView-DiaM3Lue.js +2 -0
  25. package/dist/assets/PublicLogsView-DiaM3Lue.js.map +1 -0
  26. package/dist/assets/RegistriesView-B4_mlmfk.js +2 -0
  27. package/dist/assets/RegistriesView-B4_mlmfk.js.map +1 -0
  28. package/dist/assets/RoutingView-BdDmKEyt.js +8 -0
  29. package/dist/assets/RoutingView-BdDmKEyt.js.map +1 -0
  30. package/dist/assets/SettingsView-DGCUHaEa.js +2 -0
  31. package/dist/assets/SettingsView-DGCUHaEa.js.map +1 -0
  32. package/dist/assets/SpecView-DLJmZfcg.js +2 -0
  33. package/dist/assets/SpecView-DLJmZfcg.js.map +1 -0
  34. package/dist/assets/SpecsView-C5pGVmTz.js +2 -0
  35. package/dist/assets/SpecsView-C5pGVmTz.js.map +1 -0
  36. package/dist/assets/SsoView-BipGP6-f.css +1 -0
  37. package/dist/assets/SsoView-bu6hnfgi.js +2 -0
  38. package/dist/assets/SsoView-bu6hnfgi.js.map +1 -0
  39. package/dist/assets/SubmitView-Pn5RI-pQ.js +5 -0
  40. package/dist/assets/SubmitView-Pn5RI-pQ.js.map +1 -0
  41. package/dist/assets/SubmitView-vnNiLimF.css +1 -0
  42. package/dist/assets/SwarmView-BW36b2OW.js +2 -0
  43. package/dist/assets/SwarmView-BW36b2OW.js.map +1 -0
  44. package/dist/assets/UsersView-C9v4aLDt.js +2 -0
  45. package/dist/assets/UsersView-C9v4aLDt.js.map +1 -0
  46. package/dist/assets/VarEditor-CrEUwpXW.css +1 -0
  47. package/dist/assets/VarEditor-DYmuml3i.js +4 -0
  48. package/dist/assets/VarEditor-DYmuml3i.js.map +1 -0
  49. package/dist/assets/VariablesView-D92ymqfM.css +1 -0
  50. package/dist/assets/VariablesView-tY-jjPvM.js +3 -0
  51. package/dist/assets/VariablesView-tY-jjPvM.js.map +1 -0
  52. package/dist/assets/_commonjsHelpers-CqkleIqs.js +2 -0
  53. package/dist/assets/_commonjsHelpers-CqkleIqs.js.map +1 -0
  54. package/dist/assets/_plugin-vue_export-helper-DlAUqK2U.js +2 -0
  55. package/dist/assets/_plugin-vue_export-helper-DlAUqK2U.js.map +1 -0
  56. package/dist/assets/addon-fit-CevVMrUA.js +2 -0
  57. package/dist/assets/addon-fit-CevVMrUA.js.map +1 -0
  58. package/dist/assets/api-control-rHTQCPsG.js +2 -0
  59. package/dist/assets/api-control-rHTQCPsG.js.map +1 -0
  60. package/dist/assets/api-core-DUb3ejZ0.js +2 -0
  61. package/dist/assets/api-core-DUb3ejZ0.js.map +1 -0
  62. package/dist/assets/api-deployment-HPEzQSZD.js +2 -0
  63. package/dist/assets/api-deployment-HPEzQSZD.js.map +1 -0
  64. package/dist/assets/deployments-CDLMPXV3.js +2 -0
  65. package/dist/assets/deployments-CDLMPXV3.js.map +1 -0
  66. package/dist/assets/format-Dr8IZDXn.js +2 -0
  67. package/dist/assets/format-Dr8IZDXn.js.map +1 -0
  68. package/dist/assets/hostcfg-Dub2pvbc.js +2 -0
  69. package/dist/assets/hostcfg-Dub2pvbc.js.map +1 -0
  70. package/dist/assets/index-B0aG0aPW.css +1 -0
  71. package/dist/assets/index-Cthapg0Q.js +32 -0
  72. package/dist/assets/index-Cthapg0Q.js.map +1 -0
  73. package/dist/assets/jobs-Bz_YeOAs.js +2 -0
  74. package/dist/assets/jobs-Bz_YeOAs.js.map +1 -0
  75. package/dist/assets/labels-wffzJI2t.js +2 -0
  76. package/dist/assets/labels-wffzJI2t.js.map +1 -0
  77. package/dist/assets/now-C-iOYv8-.js +2 -0
  78. package/dist/assets/now-C-iOYv8-.js.map +1 -0
  79. package/dist/assets/problem-Cs7tz86T.js +2 -0
  80. package/dist/assets/problem-Cs7tz86T.js.map +1 -0
  81. package/dist/assets/settings-problem-FNvf54oZ.js +2 -0
  82. package/dist/assets/settings-problem-FNvf54oZ.js.map +1 -0
  83. package/dist/assets/specs-BeT22mvD.css +1 -0
  84. package/dist/assets/specs-C68KO8RX.js +41 -0
  85. package/dist/assets/specs-C68KO8RX.js.map +1 -0
  86. package/dist/assets/use-logs-BD6ml1rA.js +4 -0
  87. package/dist/assets/use-logs-BD6ml1rA.js.map +1 -0
  88. package/dist/assets/use-slash-focus-BeKibFvm.js +2 -0
  89. package/dist/assets/use-slash-focus-BeKibFvm.js.map +1 -0
  90. package/dist/assets/varformats-DSwvKZLe.js +12 -0
  91. package/dist/assets/varformats-DSwvKZLe.js.map +1 -0
  92. package/dist/assets/vars-C8sghQal.js +2 -0
  93. package/dist/assets/vars-C8sghQal.js.map +1 -0
  94. package/dist/assets/xterm-D6Mng-DB.js +10 -0
  95. package/dist/assets/xterm-D6Mng-DB.js.map +1 -0
  96. package/dist/index.html +15 -0
  97. package/nginx.conf +68 -0
  98. package/package.json +34 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sami Mishal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,50 @@
1
- # Temporary Holding Version
1
+ # @samyx/preview-stacks-ui-hearth
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An alternative web UI for pstack, built on [Hearth UI](https://hearth-ui.samyx.net/llms.txt) rather
4
+ than ported from `apps/ui`: it uses the components Hearth ships for each job instead of rebuilding
5
+ the advanced UI's screens. It covers what `apps/ui` does and is selectable as a control-plane UI:
6
+ `pstack init --ui hearth`.
7
+
8
+ | Job | Hearth component |
9
+ |---|---|
10
+ | Frame, navigation, account | `HDashboardShell`, `HCommandPalette` (Ctrl/Cmd+K), `HTheme`, `HThemeSwitcher`, `HPopover` |
11
+ | Sign in | `HAuthPage` |
12
+ | Overview | `HPageHeader` (hero), `HStatCard`, `HSparkline`, `HTimeline` |
13
+ | Deployments list | `HDataTable` (sort, select, page, row actions), `HFilterBar`, `HChipGroup`, `HToolbar`, `HAlertDialog` |
14
+ | One deployment | `HResourceDetail`, `HDropdownMenu`, `HLogViewer`, `HCopyField`, `HSwitch`, `HSelect` |
15
+ | One job | `HResourceDetail`, `HStepper`, `HLogViewer`, `HProgress` |
16
+ | Feedback | `HToaster`, `HConnectionState`, `HAlert`, `HEmptyState`, `HSkeleton`, `HErrorPage` |
17
+
18
+ ## Why a separate app, not a switch inside `apps/ui`
19
+
20
+ - A runtime switch would put two implementations of every view behind one router and ship both
21
+ component libraries in one bundle. Neither UI could change without the other.
22
+ - The two already share what matters: the API, through `@samyx/preview-stacks-client`'s types. This
23
+ app has its own thin `src/api.ts` and no code from `apps/ui`.
24
+ - Choosing one is a deployment choice: `pstack init --ui basic|advanced|hearth`, or `pstack ui hearth`
25
+ on a running host. `hearth` runs this app's image as the same `advanced-ui` compose service.
26
+
27
+ ## Run
28
+
29
+ ```bash
30
+ PSTACK_TOKEN=… pstack serve # 127.0.0.1:7878
31
+ cd apps/ui-hearth && bun run dev # 127.0.0.1:5274, /api → 7878
32
+ ```
33
+
34
+ `bun run build` type-checks and builds `dist/`.
35
+
36
+ ## Deploy
37
+
38
+ ```bash
39
+ # from a checkout, at the repo root
40
+ docker build -f apps/ui-hearth/Dockerfile -t pstack-ui-hearth:local .
41
+ # or, with a built dist/ (nginx.conf beside it)
42
+ pstack build-image --ui hearth --ui-dist apps/ui-hearth/dist
43
+
44
+ pstack init --ui hearth --domain <preview.example.com> --acme-email <you@example.com>
45
+ pstack ui hearth # switch an existing host
46
+ ```
47
+
48
+ The image is `pstack-ui-hearth:local`; `PSTACK_UI_HEARTH_IMAGE` overrides it. A bare `--ui` on
49
+ `build-image` still builds the advanced image. Without `--ui-dist`, `build-image --ui hearth` fetches
50
+ `@samyx/preview-stacks-ui-hearth` from npm (published with each release).
@@ -0,0 +1 @@
1
+ .narrow[data-v-829df318]{max-width:560px}
@@ -0,0 +1,4 @@
1
+ import{d as D,c as m,w as i,u as a,N as g,f as l,I as E,D as I,g as b,j as v,ag as K,S as L,Q as T,h as c,F as C,i as M,U as G,n as y,x as A,a0 as F,G as P,J,r as o,A as x,M as O,e as s,t as Q,C as R}from"./index-Cthapg0Q.js";import{h as q,f as H,p as W}from"./hostcfg-Dub2pvbc.js";import{_ as X}from"./_plugin-vue_export-helper-DlAUqK2U.js";const Y={key:0},Z={key:1},ee=D({__name:"ConfigView",setup(ae){const h=o([]),k=o(""),f=o(""),d=o(""),p=o(""),N=o(!1),u=o(null),r=o(null),w=o(!1),V=o(0),_=x(()=>R("admin",I));function $(){u.value=null,r.value=null,p.value=""}async function U(n){h.value=n,$(),k.value=n[0]?await n[0].text():""}async function j(n){p.value="",d.value=n;const e=await q.sealed(k.value,f.value,n==="preview");if(d.value="",w.value=!1,!e.ok){N.value=e.status===403,p.value=H(e);return}if(n==="preview"){u.value=e.body;return}const t=e.body;r.value=t,u.value=null,f.value="",h.value=[],k.value="",V.value++,O("Applied","success",`${t.created.length} created, ${t.skipped.length} already here`)}const z=x(()=>u.value?W(u.value).map(n=>({key:n.key,label:n.label,value:n.value})):[]),S=x(()=>_.value&&!!k.value&&!!f.value&&!d.value);return(n,e)=>(s(),m(a(g),{direction:"column",gap:4},{default:i(()=>[l(a(E),{title:"Apply a configuration",description:"A sealed export from another host. Creates what is missing; never overwrites."}),a(I).checked&&!_.value?(s(),m(a(b),{key:0,tone:"info",title:"Admin only",description:"Applying a configuration needs an admin."})):v("",!0),l(a(g),{direction:"column",gap:3,class:"narrow"},{default:i(()=>[l(a(K),{label:"Sealed export",description:"Up to 8 MiB.",accept:".sealed,.yaml,.yml,.json,application/json","model-value":h.value,"reset-key":V.value,"max-size":8388608,onChange:U,onReject:e[0]||(e[0]=t=>p.value=t.map(B=>`${B.name}: ${B.reason}`).join("; "))},null,8,["model-value","reset-key"]),l(a(L),{modelValue:f.value,"onUpdate:modelValue":[e[1]||(e[1]=t=>f.value=t),$],label:"Passphrase",type:"password",autocomplete:"off",hint:"Sent to this host to open the file."},null,8,["modelValue"]),l(a(g),{direction:"row",gap:2,wrap:""},{default:i(()=>[l(a(T),{variant:"secondary",label:"Preview",loading:d.value==="preview",disabled:!S.value,onClick:e[2]||(e[2]=t=>j("preview"))},null,8,["loading","disabled"]),l(a(T),{variant:"danger",label:"Apply",loading:d.value==="apply",disabled:!S.value||!u.value,onClick:e[3]||(e[3]=t=>w.value=!0)},null,8,["loading","disabled"])]),_:1})]),_:1}),p.value?(s(),m(a(b),{key:1,tone:"danger",title:N.value?"Forbidden":"Not applied",description:p.value},null,8,["title","description"])):v("",!0),u.value?(s(),m(a(g),{key:2,direction:"column",gap:3,class:"narrow"},{default:i(()=>[l(a(b),{tone:"warning",title:"This file makes this host trust",description:"Nothing is written yet."},{default:i(()=>[u.value.trusts.length?(s(),c("ul",Y,[(s(!0),c(C,null,M(u.value.trusts,t=>(s(),c("li",{key:t},Q(t),1))),128))])):(s(),c("span",Z,"Nothing new."))]),_:1}),l(a(G),{items:z.value,columns:2,dense:""},null,8,["items"])]),_:1})):v("",!0),r.value?(s(),m(a(g),{key:3,direction:"column",gap:2,class:"narrow"},{default:i(()=>[l(a(b),{tone:"success",title:"Applied"}),r.value.created.length?(s(),c(C,{key:0},[l(a(A),{weight:"bold"},{default:i(()=>[...e[6]||(e[6]=[y("Created",-1)])]),_:1}),l(a(F),{code:r.value.created.join(`
2
+ `)},null,8,["code"])],64)):v("",!0),r.value.skipped.length?(s(),c(C,{key:1},[l(a(A),{weight:"bold",tone:"muted"},{default:i(()=>[...e[7]||(e[7]=[y("Already here",-1)])]),_:1}),l(a(F),{code:r.value.skipped.join(`
3
+ `)},null,8,["code"])],64)):v("",!0)]),_:1})):v("",!0),l(a(A),{size:"sm",tone:"muted"},{default:i(()=>[...e[8]||(e[8]=[y(" Take an export with ",-1),P("code",null,"pstack pull config -o host.sealed",-1),y(" using the host's ",-1),P("code",null,"PSTACK_TOKEN",-1),y(". ",-1)])]),_:1}),l(a(J),{open:w.value,title:"Apply this configuration?",description:"It can add admins, tokens and registries.","confirm-label":"Apply",danger:"",busy:d.value==="apply",onCancel:e[4]||(e[4]=t=>w.value=!1),onConfirm:e[5]||(e[5]=t=>j("apply"))},null,8,["open","busy"])]),_:1}))}}),se=X(ee,[["__scopeId","data-v-829df318"]]);export{se as default};
4
+ //# sourceMappingURL=ConfigView-nQLAHdV-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigView-nQLAHdV-.js","sources":["../../src/views/ConfigView.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Apply a sealed host configuration. No export here: `GET /api/config` answers only the\n * PSTACK_TOKEN bearer, so a browser session cannot take one. Preview first; apply is confirmed.\n */\nimport { computed, ref } from 'vue';\nimport {\n HAlert,\n HAlertDialog,\n HButton,\n HCodeBlock,\n HDescriptionList,\n HFileUpload,\n HInput,\n HPageHeader,\n HStack,\n HText,\n} from '@hearth-ui/vue';\nimport { failure, hostcfg } from '../api-hostcfg';\nimport { previewCounts, type Applied, type Preview } from '../lib/hostcfg';\nimport { can } from '../lib/users';\nimport { auth, toast } from '../state';\n\nconst files = ref<File[]>([]);\nconst sealed = ref('');\nconst passphrase = ref('');\nconst busy = ref<'' | 'preview' | 'apply'>('');\nconst error = ref('');\nconst forbidden = ref(false);\nconst preview = ref<Preview | null>(null);\nconst applied = ref<Applied | null>(null);\nconst confirm = ref(false);\nconst reset = ref(0);\nconst admin = computed(() => can('admin', auth));\n\nfunction drop(): void {\n preview.value = null;\n applied.value = null;\n error.value = '';\n}\n\n/** Read in the browser; a new file clears any preview so it can never describe another file. */\nasync function pick(f: File[]): Promise<void> {\n files.value = f;\n drop();\n sealed.value = f[0] ? await f[0].text() : '';\n}\n\nasync function run(mode: 'preview' | 'apply'): Promise<void> {\n error.value = '';\n busy.value = mode;\n const r = await hostcfg.sealed(sealed.value, passphrase.value, mode === 'preview');\n busy.value = '';\n confirm.value = false;\n if (!r.ok) {\n forbidden.value = r.status === 403;\n error.value = failure(r);\n return;\n }\n if (mode === 'preview') {\n preview.value = r.body as Preview;\n return;\n }\n const done = r.body as Applied;\n applied.value = done;\n preview.value = null;\n passphrase.value = '';\n files.value = [];\n sealed.value = '';\n reset.value++;\n toast('Applied', 'success', `${done.created.length} created, ${done.skipped.length} already here`);\n}\n\nconst counts = computed(() => (preview.value ? previewCounts(preview.value).map((c) => ({ key: c.key, label: c.label, value: c.value })) : []));\nconst ready = computed(() => admin.value && !!sealed.value && !!passphrase.value && !busy.value);\n</script>\n\n<template>\n <HStack direction=\"column\" :gap=\"4\">\n <HPageHeader title=\"Apply a configuration\" description=\"A sealed export from another host. Creates what is missing; never overwrites.\" />\n\n <HAlert v-if=\"auth.checked && !admin\" tone=\"info\" title=\"Admin only\" description=\"Applying a configuration needs an admin.\" />\n\n <HStack direction=\"column\" :gap=\"3\" class=\"narrow\">\n <HFileUpload\n label=\"Sealed export\"\n description=\"Up to 8 MiB.\"\n accept=\".sealed,.yaml,.yml,.json,application/json\"\n :model-value=\"files\"\n :reset-key=\"reset\"\n :max-size=\"8388608\"\n @change=\"pick\"\n @reject=\"(r) => (error = r.map((x) => `${x.name}: ${x.reason}`).join('; '))\"\n />\n <HInput\n v-model=\"passphrase\"\n label=\"Passphrase\"\n type=\"password\"\n autocomplete=\"off\"\n hint=\"Sent to this host to open the file.\"\n @update:model-value=\"drop\"\n />\n <HStack direction=\"row\" :gap=\"2\" wrap>\n <HButton variant=\"secondary\" label=\"Preview\" :loading=\"busy === 'preview'\" :disabled=\"!ready\" @click=\"run('preview')\" />\n <HButton variant=\"danger\" label=\"Apply\" :loading=\"busy === 'apply'\" :disabled=\"!ready || !preview\" @click=\"confirm = true\" />\n </HStack>\n </HStack>\n\n <HAlert v-if=\"error\" tone=\"danger\" :title=\"forbidden ? 'Forbidden' : 'Not applied'\" :description=\"error\" />\n\n <HStack v-if=\"preview\" direction=\"column\" :gap=\"3\" class=\"narrow\">\n <HAlert tone=\"warning\" title=\"This file makes this host trust\" description=\"Nothing is written yet.\">\n <ul v-if=\"preview.trusts.length\">\n <li v-for=\"t in preview.trusts\" :key=\"t\">{{ t }}</li>\n </ul>\n <span v-else>Nothing new.</span>\n </HAlert>\n <HDescriptionList :items=\"counts\" :columns=\"2\" dense />\n </HStack>\n\n <HStack v-if=\"applied\" direction=\"column\" :gap=\"2\" class=\"narrow\">\n <HAlert tone=\"success\" title=\"Applied\" />\n <template v-if=\"applied.created.length\">\n <HText weight=\"bold\">Created</HText>\n <HCodeBlock :code=\"applied.created.join('\\n')\" />\n </template>\n <template v-if=\"applied.skipped.length\">\n <HText weight=\"bold\" tone=\"muted\">Already here</HText>\n <HCodeBlock :code=\"applied.skipped.join('\\n')\" />\n </template>\n </HStack>\n\n <HText size=\"sm\" tone=\"muted\">\n Take an export with <code>pstack pull config -o host.sealed</code> using the host's <code>PSTACK_TOKEN</code>.\n </HText>\n\n <HAlertDialog\n :open=\"confirm\"\n title=\"Apply this configuration?\"\n description=\"It can add admins, tokens and registries.\"\n confirm-label=\"Apply\"\n danger\n :busy=\"busy === 'apply'\"\n @cancel=\"confirm = false\"\n @confirm=\"run('apply')\"\n />\n </HStack>\n</template>\n\n<style scoped>\n.narrow {\n max-width: 560px;\n}\n</style>\n"],"names":["files","ref","sealed","passphrase","busy","error","forbidden","preview","applied","confirm","reset","admin","computed","can","auth","drop","pick","f","run","mode","r","hostcfg","failure","done","toast","counts","previewCounts","c","ready","_createBlock","_unref","HStack","_createVNode","HPageHeader","HAlert","HFileUpload","x","HInput","$event","HButton","_createElementBlock","_hoisted_1","_openBlock","_Fragment","_renderList","HDescriptionList","HText","_cache","HCodeBlock","_createElementVNode","HAlertDialog"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{d as Z,c as s,u as e,B as q,w as d,g as j,Z as ce,q as fe,m as ge,h as E,F as T,n as h,t as ee,l as N,j as B,f as i,J as _,A as D,r as f,M as P,e as n,N as U,U as ye,Q as z,x as G,ah as ne,G as pe,s as ke,v as ie,i as be,S as F,al as we,am as Se,O as Ve,an as Ae,ad as Ce,ao as Q,V as Re,ap as xe,W as oe,k as Be,I as Me,p as W,D as re}from"./index-Cthapg0Q.js";import{c as I,w as O,p as X}from"./api-control-rHTQCPsG.js";import{c as $e,a as De,s as Ke}from"./format-Dr8IZDXn.js";import{b as Pe}from"./labels-wffzJI2t.js";import{_ as he}from"./_plugin-vue_export-helper-DlAUqK2U.js";const se=["viewer","developer","maintainer","admin"];function Ue(l,m,r){if(l)return!0;const w=se.indexOf(m??"")+1;return w>0&&w>=se.indexOf(r)+1}function Ie(l){return l===null?"unlimited":l>=1024**3?`${(l/1024**3).toFixed(1)} GiB`:`${Math.round(l/1024**2)} MiB`}function ue(l,m=Date.now()){return Math.floor((l-m)/864e5)}function Le(l,m=new Date().toISOString().slice(0,10)){return l?l.cutover>m?`S3 from ${l.cutover}`:"S3":"Filesystem"}function Ne(l,m,r){const w=l.trim().toLowerCase();return w?w.includes("://")||w.includes("/")||/\s/.test(w)?"A hostname only.":w===r||m.includes(w)?"Already listed.":"":"Type a domain."}function Y(l,m){return l===null||!Number.isInteger(l)?"A whole number.":l<m.min||l>m.max?`${m.min} to ${m.max}.`:""}function Ee(l,m){const r=m.findIndex(w=>w.id===l.id);return r<0?null:m.slice(0,r).reverse().find(w=>w.stack===l.stack)??null}const ze=l=>!["queued","running"].includes(l),Oe=Z({__name:"ContainersCard",props:{runtime:{},loaded:{type:Boolean},error:{},canRestart:{type:Boolean}},emits:["reload"],setup(l,{emit:m}){const r=l,w=m,S=[{key:"service",label:"Service"},{key:"image",label:"Image",truncate:!0,hideBelow:760},{key:"state",label:"State"},{key:"restarts",label:"Restarts"},{key:"mem",label:"Memory limit",hideBelow:560},{key:"started",label:"Started",hideBelow:640}],x=D(()=>{var y;return((y=r.runtime)==null?void 0:y.containers)??[]}),V=D(()=>Pe(x.value,y=>y.name,y=>y.id)),p=D(()=>[...V.value].map(([y,v])=>({id:y,service:v.service||v.name,image:v.image,state:v.state,restarts:v.restartCount,mem:Ie(v.memLimitBytes),started:De(v.startedAt)}))),M=y=>V.value.get(y),k=y=>{const v=M(y.id);return!r.canRestart||!(v!=null&&v.service)||v.service==="pstack"?[]:[{id:"restart",label:"Restart",icon:"arrow"}]},A=f({open:!1,service:""}),c=f(!1);function g(y){const v=M(y.id);v!=null&&v.service&&y.action==="restart"&&(A.value={open:!0,service:v.service})}async function $(){const y=A.value.service;c.value=!0;const v=await I.restart(y);if(c.value=!1,A.value.open=!1,!v.ok){P(O(v,`Restart ${y}`),"danger");return}P(`Restarting ${v.body.container}.`,"success"),w("reload")}return(y,v)=>(n(),s(e(q),{title:"Containers"},{default:d(()=>[l.error?(n(),s(e(j),{key:0,tone:"danger",title:l.error},null,8,["title"])):l.loaded?l.runtime&&!l.runtime.reachable?(n(),s(e(j),{key:2,tone:"warning",title:"Docker is not answering.",description:"Nothing here is known."})):p.value.length?(n(),s(e(ge),{key:4,label:"Control containers",rows:p.value,columns:S,"get-row-actions":k,onRowAction:g},{cell:d(({row:u,column:b,value:t})=>{var C,L,H,J;return[b.key==="service"?(n(),E(T,{key:0},[h(ee(t)+" ",1),t==="pstack"?(n(),s(e(N),{key:0,tone:"info",label:"This API",size:"sm"})):B("",!0),t==="pstack"?(n(),s(e(N),{key:1,tone:"neutral",label:"Restart from the host",size:"sm"})):B("",!0)],64)):b.key==="state"?(n(),s(e(N),{key:1,tone:e($e)(String(t),((C=M(String(u.id)))==null?void 0:C.health)??null),label:(L=M(String(u.id)))!=null&&L.health?`${t} · ${(H=M(String(u.id)))==null?void 0:H.health}`:String(t)},null,8,["tone","label"])):b.key==="restarts"?(n(),E(T,{key:2},[i(e(N),{tone:Number(t)>0?"warning":"neutral",label:String(t)},null,8,["tone","label"]),(J=M(String(u.id)))!=null&&J.oomKilled?(n(),s(e(N),{key:0,tone:"danger",label:"OOM"})):B("",!0)],64)):(n(),E(T,{key:3},[h(ee(t),1)],64))]}),_:1},8,["rows"])):(n(),s(e(fe),{key:3,title:"None listed",icon:"server"})):(n(),s(e(ce),{key:1,variant:"rectangle"})),i(e(_),{open:A.value.open,"onUpdate:open":v[0]||(v[0]=u=>A.value.open=u),title:`Restart ${A.value.service}?`,"confirm-label":"Restart",busy:c.value,onConfirm:$},null,8,["open","title","busy"])]),_:1}))}}),Te=Z({__name:"CertificatesCard",props:{tls:{},canAdmin:{type:Boolean}},emits:["reload"],setup(l,{emit:m}){const r=l,w=m,S=f(""),x=f(""),V=f(!1),p=f(!1),M=f(!1),k=f(!1),A=f(null),c=D(()=>r.tls.wildcard?ue(r.tls.wildcard.notAfter):null),g=D(()=>{const u=r.tls.wildcard;return u?[{key:"covers",label:"Covers",value:u.domains.join(", ")},{key:"until",label:"Valid until",value:Ke(u.notAfter)},{key:"issuer",label:"Issuer",value:u.issuer||"unnamed"}]:[]});async function $(){V.value=!0;const u=await I.storeWildcard(S.value,x.value);if(V.value=!1,!u.ok){P(O(u,"Store the wildcard"),"danger");return}S.value=x.value="",A.value=null,P("Stored. Redeploy all stacks.","success"),w("reload")}async function y(){p.value=!0;const u=await I.removeWildcard();if(p.value=!1,M.value=!1,!u.ok){P(O(u,"Remove the wildcard"),"danger");return}A.value=null,P("Removed. Redeploy all stacks.","success"),w("reload")}async function v(){k.value=!0;const u=await I.redeploy();if(k.value=!1,!u.ok){P(O(u,"Redeploy the stacks"),"danger");return}A.value=u.body,P(`Redeploying ${u.body.started.length}, skipped ${u.body.skipped.length}.`,"success")}return(u,b)=>(n(),s(e(q),{title:"Certificates"},{default:d(()=>[i(e(U),{gap:4,direction:"column"},{default:d(()=>{var t;return[i(e(U),{direction:"row",gap:2,wrap:"",align:"center"},{default:d(()=>{var C;return[i(e(N),{tone:l.tls.mode==="dns-persist-01"?"success":"info",label:l.tls.mode},null,8,["tone","label"]),c.value!==null?(n(),s(e(N),{key:0,tone:c.value<21?"danger":"neutral",label:`${c.value} days left`},null,8,["tone","label"])):B("",!0),(C=l.tls.wildcard)!=null&&C.selfSigned?(n(),s(e(N),{key:1,tone:"warning",label:"Self-signed"})):B("",!0)]}),_:1}),g.value.length?(n(),s(e(ye),{key:0,items:g.value,variant:"inline"},null,8,["items"])):B("",!0),(t=l.tls.wildcard)!=null&&t.selfSigned?(n(),s(e(j),{key:1,tone:"warning",title:"Browsers will warn.",compact:""})):B("",!0),l.tls.wildcard&&l.canAdmin?(n(),s(e(U),{key:2,direction:"row",gap:3,align:"center",wrap:""},{default:d(()=>[i(e(z),{variant:"danger",loading:p.value,onClick:b[0]||(b[0]=C=>M.value=!0)},{default:d(()=>[...b[4]||(b[4]=[h("Remove wildcard",-1)])]),_:1},8,["loading"]),i(e(G),{tone:"muted"},{default:d(()=>[...b[5]||(b[5]=[h("Stacks under it serve no certificate until redeployed.",-1)])]),_:1})]),_:1})):B("",!0),l.canAdmin?(n(),E(T,{key:3},[i(e(ne),{modelValue:S.value,"onUpdate:modelValue":b[1]||(b[1]=C=>S.value=C),label:"Certificate (PEM, leaf first)",rows:5,placeholder:"-----BEGIN CERTIFICATE-----",hint:"Stored 0600. Never returned."},null,8,["modelValue"]),i(e(ne),{modelValue:x.value,"onUpdate:modelValue":b[2]||(b[2]=C=>x.value=C),label:"Private key (PEM)",rows:4,placeholder:"-----BEGIN PRIVATE KEY-----"},null,8,["modelValue"]),pe("div",null,[i(e(z),{variant:"primary",loading:V.value,disabled:!S.value.trim()||!x.value.trim(),onClick:$},{default:d(()=>[h(ee(l.tls.wildcard?"Replace wildcard":"Store wildcard"),1)]),_:1},8,["loading","disabled"])])],64)):l.tls.wildcard?B("",!0):(n(),s(e(G),{key:4,tone:"muted"},{default:d(()=>[...b[6]||(b[6]=[h("Admin only.",-1)])]),_:1})),i(e(U),{direction:"row",gap:3,align:"center",wrap:""},{default:d(()=>[i(e(z),{loading:k.value,onClick:v},{default:d(()=>[...b[7]||(b[7]=[h("Redeploy all stacks",-1)])]),_:1},8,["loading"]),i(e(G),{tone:"muted"},{default:d(()=>[...b[8]||(b[8]=[h("Asleep stacks pick up new labels on wake.",-1)])]),_:1})]),_:1}),A.value?(n(),s(e(j),{key:5,tone:"info",title:`Started ${A.value.started.length}, skipped ${A.value.skipped.length}`,description:A.value.skipped.map(C=>`${C.id}: ${C.reason}`).join("; ")||void 0,compact:""},null,8,["title","description"])):B("",!0)]}),_:1}),i(e(_),{open:M.value,"onUpdate:open":b[3]||(b[3]=t=>M.value=t),danger:"",title:"Remove the wildcard?",description:"Deployed stacks lose TLS.","confirm-label":"Remove",busy:p.value,onConfirm:y},null,8,["open","busy"])]),_:1}))}}),je=Z({__name:"DomainsCard",props:{domains:{},canEdit:{type:Boolean}},emits:["reload"],setup(l,{emit:m}){const r=l,w=m,S=f(""),x=f(!1),V=f(""),p=D(()=>S.value?Ne(S.value,r.domains.domains,r.domains.primary):"");async function M(c){x.value=!0;const g=await I.saveDomains(c);return x.value=!1,g.ok?(P("Domains saved.","success"),w("reload"),!0):(P(O(g,"Save the domains"),"danger"),!1)}async function k(){p.value||!S.value.trim()||await M([...r.domains.domains,S.value.trim().toLowerCase()])&&(S.value="")}async function A(){const c=V.value;await M(r.domains.domains.filter(g=>g!==c)),V.value=""}return(c,g)=>(n(),s(e(q),{title:"Domains"},{default:d(()=>[i(e(U),{gap:3,direction:"column"},{default:d(()=>[i(e(ke),{label:"Domains"},{default:d(()=>[i(e(ie),{title:l.domains.primary||"Not set",description:"Primary"},null,8,["title"]),(n(!0),E(T,null,be(l.domains.domains,$=>(n(),s(e(ie),{key:$,title:$,description:`control.${$} · api.${$}`},Se({_:2},[l.canEdit?{name:"trailing",fn:d(()=>[i(e(z),{variant:"ghost",size:"compact",label:`Remove ${$}`,disabled:x.value,onClick:y=>V.value=$},{default:d(()=>[...g[2]||(g[2]=[h("Remove",-1)])]),_:1},8,["label","disabled","onClick"])]),key:"0"}:void 0]),1032,["title","description"]))),128))]),_:1}),l.canEdit?(n(),s(e(U),{key:0,direction:"row",gap:3,wrap:"",align:"end"},{default:d(()=>[i(e(F),{modelValue:S.value,"onUpdate:modelValue":g[0]||(g[0]=$=>S.value=$),label:"Add a domain",placeholder:"preview.example.com",error:p.value,onKeyup:we(k,["enter"])},null,8,["modelValue","error"]),i(e(z),{variant:"primary",loading:x.value,disabled:!S.value.trim()||!!p.value,onClick:k},{default:d(()=>[...g[3]||(g[3]=[h("Add",-1)])]),_:1},8,["loading","disabled"])]),_:1})):(n(),s(e(G),{key:1,tone:"muted"},{default:d(()=>[...g[4]||(g[4]=[h("Maintainer only.",-1)])]),_:1}))]),_:1}),i(e(_),{open:!!V.value,danger:"",title:`Remove ${V.value}?`,"confirm-label":"Remove",busy:x.value,"onUpdate:open":g[1]||(g[1]=$=>!$&&(V.value="")),onConfirm:A},null,8,["open","title","busy"])]),_:1}))}}),Fe={key:1},Je=Z({__name:"LoggingCard",props:{canAdmin:{type:Boolean}},setup(l){const m=l,r=f(null),w=f(!1),S=f(""),x=f(""),V=f(!1),p=f(null),M=()=>({retentionDays:null,idlePeriodMinutes:null,maxAgeMinutes:null,targetSizeKiB:null,encoding:""}),k=f(M()),A=f(M()),c=f({endpoint:"",region:"",bucket:"",pathStyle:!1,accessKeyId:""}),g=f(""),$=f(!1),y=f(!1);Ve(()=>r.value&&JSON.stringify([r.value.retentionDays,r.value.chunks,r.value.storage]),()=>{const o=r.value;if(!o)return;A.value={retentionDays:o.retentionDays,...o.chunks},k.value={...A.value},$.value=o.storage.type==="s3";const a=o.storage.s3;c.value={endpoint:(a==null?void 0:a.endpoint)??"",region:(a==null?void 0:a.region)??"",bucket:(a==null?void 0:a.bucket)??"",pathStyle:(a==null?void 0:a.pathStyle)??!1,accessKeyId:(a==null?void 0:a.accessKeyId)??""}});const v=D(()=>{var o;return((o=r.value)==null?void 0:o.storage.type)==="s3"}),u=D(()=>v.value||!m.canAdmin),b=D(()=>JSON.stringify(k.value)!==JSON.stringify(A.value)),t=D(()=>{var o;return(o=r.value)==null?void 0:o.limits}),C=D(()=>{const o=t.value;if(!o)return{};const a=k.value;return{retentionDays:Y(a.retentionDays,o.retentionDays),idlePeriodMinutes:Y(a.idlePeriodMinutes,o.idlePeriodMinutes),maxAgeMinutes:Y(a.maxAgeMinutes,o.maxAgeMinutes),targetSizeKiB:Y(a.targetSizeKiB,o.targetSizeKiB)}}),L=D(()=>Object.values(C.value).every(o=>!o)&&!!k.value.encoding),H=D(()=>{var o;return(((o=t.value)==null?void 0:o.encodings)??[]).map(a=>({value:a,label:a}))}),J=D(()=>!!(c.value.endpoint.trim()&&c.value.region.trim()&&c.value.bucket.trim()&&c.value.accessKeyId.trim()&&(v.value||g.value)));async function de(o){var K;const a=await I.job(o);if(p.value!==o)return;if(a.status===404){p.value=null;return}if(!a.ok||!ze(a.body.job.state))return;const R=a.body.job;if(R.state==="superseded"){p.value=((K=Ee(R,Be.jobs))==null?void 0:K.id)??o;return}p.value=null,R.state==="ok"?P("Applied.","success"):R.state==="cancelled"?P("Cancelled.","warning"):P("Apply failed.","danger",`Job ${R.id}`)}async function ae(){p.value&&await de(p.value);const o=await I.logging();w.value=!0,o.ok?(r.value=o.body,S.value=""):o.status!==403?S.value=O(o,"Read the logging settings"):S.value="Maintainer only."}X(ae,1e4);async function le(o){V.value=!0;const a=await o;if(V.value=!1,!a.ok){x.value=O(a,"Save");return}x.value="",g.value="","job"in a.body?(p.value=a.body.job.id,P("Applying.","info")):P("No change.","success"),await ae()}const ve=()=>{const o=k.value;return le(I.saveLogging({retentionDays:o.retentionDays,chunks:{idlePeriodMinutes:o.idlePeriodMinutes,maxAgeMinutes:o.maxAgeMinutes,targetSizeKiB:o.targetSizeKiB,encoding:o.encoding}}))},me=()=>k.value={...A.value};function te(){var R;const o=r.value;if(!o)return Promise.resolve();const a={type:"s3",...c.value,secretAccessKey:g.value,cutover:((R=o.storage.s3)==null?void 0:R.cutover)??o.limits.earliestCutover};return y.value=!1,le(I.saveStorage(a))}return(o,a)=>!w.value||S.value||r.value&&r.value.enabled!==!1?(n(),s(e(q),{key:0,title:"Logging"},{default:d(()=>[S.value?(n(),s(e(j),{key:0,tone:"danger",title:S.value,compact:""},null,8,["title"])):r.value?r.value.enabled===null?(n(),s(e(j),{key:2,tone:"warning",title:"Docker did not answer.",compact:""})):(n(),s(e(U),{key:3,gap:4,direction:"column"},{default:d(()=>[i(e(U),{direction:"row",gap:2,align:"center",wrap:""},{default:d(()=>[i(e(N),{tone:"info",label:e(Le)(r.value.storage.s3)},null,8,["label"]),p.value?(n(),s(e(Ae),{key:0,to:`/jobs/${e(Ce)(p.value)}`},{default:d(()=>[i(e(N),{tone:"info",label:"Applying",dot:""})]),_:1},8,["to"])):B("",!0)]),_:1}),i(e(xe),{class:"chunks",title:"Retention and chunks",description:"Restarts Loki.",dirty:b.value,saving:V.value,error:x.value||(b.value&&!L.value?"Fix the highlighted fields.":""),onSave:a[5]||(a[5]=R=>L.value?ve():x.value="Fix the highlighted fields."),onReset:me},{default:d(()=>[i(e(U),{gap:3,direction:"column"},{default:d(()=>[i(e(Q),{modelValue:k.value.retentionDays,"onUpdate:modelValue":a[0]||(a[0]=R=>k.value.retentionDays=R),label:"Retention (days)",min:t.value.retentionDays.min,max:t.value.retentionDays.max,error:C.value.retentionDays},null,8,["modelValue","min","max","error"]),i(e(Q),{modelValue:k.value.idlePeriodMinutes,"onUpdate:modelValue":a[1]||(a[1]=R=>k.value.idlePeriodMinutes=R),label:"Chunk idle (min)",min:t.value.idlePeriodMinutes.min,max:t.value.idlePeriodMinutes.max,error:C.value.idlePeriodMinutes},null,8,["modelValue","min","max","error"]),i(e(Q),{modelValue:k.value.maxAgeMinutes,"onUpdate:modelValue":a[2]||(a[2]=R=>k.value.maxAgeMinutes=R),label:"Chunk max age (min)",min:t.value.maxAgeMinutes.min,max:t.value.maxAgeMinutes.max,error:C.value.maxAgeMinutes},null,8,["modelValue","min","max","error"]),i(e(Q),{modelValue:k.value.targetSizeKiB,"onUpdate:modelValue":a[3]||(a[3]=R=>k.value.targetSizeKiB=R),label:"Chunk size (KiB)",min:t.value.targetSizeKiB.min,max:t.value.targetSizeKiB.max,error:C.value.targetSizeKiB},null,8,["modelValue","min","max","error"]),i(e(Re),{modelValue:k.value.encoding,"onUpdate:modelValue":a[4]||(a[4]=R=>k.value.encoding=R),label:"Encoding",options:H.value},null,8,["modelValue","options"])]),_:1})]),_:1},8,["dirty","saving","error"]),i(e(q),{title:"Storage",description:u.value?l.canAdmin?"Fixed once saved.":"Admin only.":"One-way."},{default:d(()=>[i(e(U),{gap:3,direction:"column"},{default:d(()=>{var R;return[i(e(oe),{modelValue:$.value,"onUpdate:modelValue":a[6]||(a[6]=K=>$.value=K),label:"S3",disabled:u.value},null,8,["modelValue","disabled"]),$.value?(n(),E(T,{key:0},[i(e(F),{modelValue:c.value.endpoint,"onUpdate:modelValue":a[7]||(a[7]=K=>c.value.endpoint=K),type:"url",label:"Endpoint",disabled:u.value},null,8,["modelValue","disabled"]),i(e(F),{modelValue:c.value.region,"onUpdate:modelValue":a[8]||(a[8]=K=>c.value.region=K),label:"Region",disabled:u.value},null,8,["modelValue","disabled"]),i(e(F),{modelValue:c.value.bucket,"onUpdate:modelValue":a[9]||(a[9]=K=>c.value.bucket=K),label:"Bucket",disabled:u.value},null,8,["modelValue","disabled"]),i(e(oe),{modelValue:c.value.pathStyle,"onUpdate:modelValue":a[10]||(a[10]=K=>c.value.pathStyle=K),label:"Path-style",disabled:u.value},null,8,["modelValue","disabled"]),i(e(F),{modelValue:c.value.accessKeyId,"onUpdate:modelValue":a[11]||(a[11]=K=>c.value.accessKeyId=K),label:"Access key ID",autocomplete:"off",disabled:!l.canAdmin},null,8,["modelValue","disabled"]),l.canAdmin?(n(),s(e(F),{key:0,modelValue:g.value,"onUpdate:modelValue":a[12]||(a[12]=K=>g.value=K),type:"password",label:"Secret access key",autocomplete:"new-password",hint:(R=r.value.storage.s3)!=null&&R.secretSet?"Write-only. Leave empty to keep.":"Write-only."},null,8,["modelValue","hint"])):B("",!0),l.canAdmin?(n(),E("div",Fe,[v.value?(n(),s(e(z),{key:0,loading:V.value,disabled:!J.value,onClick:te},{default:d(()=>[...a[16]||(a[16]=[h("Save keys",-1)])]),_:1},8,["loading","disabled"])):(n(),s(e(z),{key:1,loading:V.value,disabled:!J.value,onClick:a[13]||(a[13]=K=>y.value=!0)},{default:d(()=>[...a[17]||(a[17]=[h("Switch to S3",-1)])]),_:1},8,["loading","disabled"]))])):B("",!0)],64)):B("",!0)]}),_:1}),i(e(_),{open:y.value,"onUpdate:open":a[14]||(a[14]=R=>y.value=R),danger:"",title:`Switch to S3 from ${r.value.limits.earliestCutover} UTC?`,description:"One-way.","confirm-label":"Switch to S3",busy:V.value,onConfirm:te},null,8,["open","title","busy"])]),_:1},8,["description"])]),_:1})):(n(),s(e(G),{key:1,tone:"muted"},{default:d(()=>[...a[15]||(a[15]=[h("Loading.",-1)])]),_:1}))]),_:1})):B("",!0)}}),We=he(Je,[["__scopeId","data-v-83888201"]]),Ye=Z({__name:"ControlView",setup(l){const m=t=>Ue(re.root,re.role,t),r=f(null),w=f(!1),S=f(""),x=f(!1),V=f(null),p=f(null);async function M(){if(!m("maintainer")){w.value=x.value=!0;return}const t=await I.runtime();if(w.value=!0,x.value=t.status===403,!t.ok){S.value=x.value?"":O(t,"Read the control stack");return}S.value="",r.value={...t.body,containers:t.body.containers??[]}}async function k(){if(!m("maintainer"))return;const t=await I.domains();t.ok&&(V.value={...t.body,domains:t.body.domains??[]})}async function A(){if(!m("maintainer"))return;const t=await I.tls();t.ok&&(p.value=t.body)}const c=()=>Promise.all([k(),A()]),g=f(!1);async function $(){g.value=!0,await Promise.all([M(),k(),A()]),g.value=!1}X(M,1e4),X(k,3e4),X(A,3e4);const y=D(()=>{var t;return(((t=r.value)==null?void 0:t.containers)??[]).reduce((C,L)=>C+L.restartCount,0)}),v=D(()=>{var t;return(((t=r.value)==null?void 0:t.containers)??[]).filter(C=>C.oomKilled).length}),u=D(()=>{var t;return(t=p.value)!=null&&t.wildcard?ue(p.value.wildcard.notAfter):null}),b=D(()=>V.value?V.value.domains.length+(V.value.primary?1:0):0);return(t,C)=>(n(),s(e(U),{gap:4,direction:"column"},{default:d(()=>{var L;return[i(e(Me),{title:"Control stack",eyebrow:"Host",description:"Containers, hostnames, certificates and logging.","actions-placement":"end"},{actions:d(()=>[i(e(z),{variant:"secondary",icon:"arrow",label:"Refresh",loading:g.value,onClick:$},null,8,["loading"])]),_:1}),x.value?(n(),s(e(j),{key:0,tone:"warning",title:"Maintainer only."})):(n(),E(T,{key:1},[(L=r.value)!=null&&L.reachable?(n(),s(e(U),{key:0,direction:"row",gap:3,wrap:""},{default:d(()=>[i(e(W),{label:"Restarts",value:y.value,tone:y.value?"warning":"neutral"},null,8,["value","tone"]),i(e(W),{label:"OOM killed",value:v.value,tone:v.value?"danger":"neutral"},null,8,["value","tone"]),p.value?(n(),s(e(W),{key:0,label:"Certificates",value:p.value.mode},null,8,["value"])):B("",!0),u.value!==null?(n(),s(e(W),{key:1,label:"Cert expires",value:`${u.value}d`,tone:u.value<21?"danger":"neutral"},null,8,["value","tone"])):B("",!0),b.value?(n(),s(e(W),{key:2,label:"Domains",value:b.value},null,8,["value"])):B("",!0)]),_:1})):B("",!0),i(Oe,{runtime:r.value,loaded:w.value,error:S.value,"can-restart":m("maintainer"),onReload:M},null,8,["runtime","loaded","error","can-restart"]),V.value?(n(),s(je,{key:1,domains:V.value,"can-edit":m("maintainer"),onReload:c},null,8,["domains","can-edit"])):B("",!0),p.value?(n(),s(Te,{key:2,tls:p.value,"can-admin":m("admin"),onReload:A},null,8,["tls","can-admin"])):B("",!0),m("maintainer")?(n(),s(We,{key:3,"can-admin":m("admin")},null,8,["can-admin"])):B("",!0)],64))]}),_:1}))}});export{Ye as default};
2
+ //# sourceMappingURL=ControlView-Cg4SUV8Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ControlView-Cg4SUV8Q.js","sources":["../../src/lib/control.ts","../../src/views/control/ContainersCard.vue","../../src/views/control/CertificatesCard.vue","../../src/views/control/DomainsCard.vue","../../src/views/control/LoggingCard.vue","../../src/views/ControlView.vue"],"sourcesContent":["import type { Job } from '@samyx/preview-stacks-client';\n\nconst ROLES = ['viewer', 'developer', 'maintainer', 'admin'] as const;\nexport type RoleName = (typeof ROLES)[number];\n\n/** Rendering only; the server decides. Root passes everything, an unknown role ranks below viewer. */\nexport function atLeast(root: boolean, role: string | null | undefined, min: RoleName): boolean {\n if (root) return true;\n const have = ROLES.indexOf((role ?? '') as RoleName) + 1;\n return have > 0 && have >= ROLES.indexOf(min) + 1;\n}\n\n/** 268435456 -> \"256 MiB\"; null -> \"unlimited\". */\nexport function mem(bytes: number | null): string {\n if (bytes === null) return 'unlimited';\n if (bytes >= 1024 ** 3) return `${(bytes / 1024 ** 3).toFixed(1)} GiB`;\n return `${Math.round(bytes / 1024 ** 2)} MiB`;\n}\n\nexport function daysLeft(notAfter: number, now = Date.now()): number {\n return Math.floor((notAfter - now) / 86_400_000);\n}\n\n/** The cutover is 00:00 UTC of its day; before it Loki still writes to the filesystem. */\nexport function storageBadge(s3: { cutover: string } | null, today = new Date().toISOString().slice(0, 10)): string {\n if (!s3) return 'Filesystem';\n return s3.cutover > today ? `S3 from ${s3.cutover}` : 'S3';\n}\n\n/** Why a domain cannot be added as typed, or ''. The server stays the authority. */\nexport function domainProblem(raw: string, existing: string[], primary: string): string {\n const d = raw.trim().toLowerCase();\n if (!d) return 'Type a domain.';\n if (d.includes('://') || d.includes('/') || /\\s/.test(d)) return 'A hostname only.';\n if (d === primary || existing.includes(d)) return 'Already listed.';\n return '';\n}\n\nexport type Range = { min: number; max: number };\n/** Why an integer box is out of range, or ''. */\nexport function rangeProblem(v: number | null, r: Range): string {\n if (v === null || !Number.isInteger(v)) return 'A whole number.';\n return v < r.min || v > r.max ? `${r.min} to ${r.max}.` : '';\n}\n\n/**\n * The job that replaced a superseded one: the nearest newer job for the same stack in a\n * newest-first list. Null when it aged out or the list has not loaded.\n */\nexport function supersededBy(job: Job, jobs: Job[]): Job | null {\n const i = jobs.findIndex((j) => j.id === job.id);\n if (i < 0) return null;\n return jobs.slice(0, i).reverse().find((j) => j.stack === job.stack) ?? null;\n}\n\nexport const isTerminal = (state: string): boolean => !['queued', 'running'].includes(state);\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { HAlertDialog, HAlert, HBadge, HCard, HDataTable, HEmptyState, HSkeleton, type MenuAction, type TableColumn, type TableRow } from '@hearth-ui/vue';\nimport { controlApi, why, type ControlRuntime } from '../../api-control';\nimport { ago, containerTone } from '../../format';\nimport { mem } from '../../lib/control';\nimport { byLabel } from '../../lib/labels';\nimport { toast } from '../../state';\n\nconst props = defineProps<{ runtime: ControlRuntime | null; loaded: boolean; error: string; canRestart: boolean }>();\nconst emit = defineEmits<{ reload: [] }>();\n\nconst columns: TableColumn[] = [\n { key: 'service', label: 'Service' },\n { key: 'image', label: 'Image', truncate: true, hideBelow: 760 },\n { key: 'state', label: 'State' },\n { key: 'restarts', label: 'Restarts' },\n { key: 'mem', label: 'Memory limit', hideBelow: 560 },\n { key: 'started', label: 'Started', hideBelow: 640 },\n];\nconst list = computed(() => props.runtime?.containers ?? []);\nconst named = computed(() => byLabel(list.value, (c) => c.name, (c) => c.id));\nconst rows = computed<TableRow[]>(() =>\n [...named.value].map(([rid, c]) => ({\n id: rid,\n service: c.service || c.name,\n image: c.image,\n state: c.state,\n restarts: c.restartCount,\n mem: mem(c.memLimitBytes),\n started: ago(c.startedAt),\n })),\n);\nconst find = (rowId: string) => named.value.get(rowId);\n\n// pstack cannot restart itself: the server refuses its own container by name.\nconst rowActions = (row: TableRow): MenuAction[] => {\n const c = find(row.id);\n if (!props.canRestart || !c?.service || c.service === 'pstack') return [];\n return [{ id: 'restart', label: 'Restart', icon: 'arrow' }];\n};\n\nconst confirm = ref({ open: false, service: '' });\nconst busy = ref(false);\nfunction onAction(e: { id: string; action: string }): void {\n const c = find(e.id);\n if (c?.service && e.action === 'restart') confirm.value = { open: true, service: c.service };\n}\nasync function restart(): Promise<void> {\n const service = confirm.value.service;\n busy.value = true;\n const r = await controlApi.restart(service);\n busy.value = false;\n confirm.value.open = false;\n if (!r.ok) {\n toast(why(r, `Restart ${service}`), 'danger');\n return;\n }\n toast(`Restarting ${r.body.container}.`, 'success');\n emit('reload');\n}\n</script>\n\n<template>\n <HCard title=\"Containers\">\n <HAlert v-if=\"error\" tone=\"danger\" :title=\"error\" />\n <HSkeleton v-else-if=\"!loaded\" variant=\"rectangle\" />\n <HAlert v-else-if=\"runtime && !runtime.reachable\" tone=\"warning\" title=\"Docker is not answering.\" description=\"Nothing here is known.\" />\n <HEmptyState v-else-if=\"!rows.length\" title=\"None listed\" icon=\"server\" />\n <HDataTable v-else label=\"Control containers\" :rows=\"rows\" :columns=\"columns\" :get-row-actions=\"rowActions\" @row-action=\"onAction\">\n <template #cell=\"{ row, column, value }\">\n <template v-if=\"column.key === 'service'\">\n {{ value }}\n <HBadge v-if=\"value === 'pstack'\" tone=\"info\" label=\"This API\" size=\"sm\" />\n <HBadge v-if=\"value === 'pstack'\" tone=\"neutral\" label=\"Restart from the host\" size=\"sm\" />\n </template>\n <HBadge\n v-else-if=\"column.key === 'state'\"\n :tone=\"containerTone(String(value), find(String(row.id))?.health ?? null)\"\n :label=\"find(String(row.id))?.health ? `${value} · ${find(String(row.id))?.health}` : String(value)\"\n />\n <template v-else-if=\"column.key === 'restarts'\">\n <HBadge :tone=\"Number(value) > 0 ? 'warning' : 'neutral'\" :label=\"String(value)\" />\n <HBadge v-if=\"find(String(row.id))?.oomKilled\" tone=\"danger\" label=\"OOM\" />\n </template>\n <template v-else>{{ value }}</template>\n </template>\n </HDataTable>\n <HAlertDialog\n v-model:open=\"confirm.open\"\n :title=\"`Restart ${confirm.service}?`\"\n confirm-label=\"Restart\"\n :busy=\"busy\"\n @confirm=\"restart\"\n />\n </HCard>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { HAlert, HAlertDialog, HBadge, HButton, HCard, HDescriptionList, HStack, HText, HTextarea } from '@hearth-ui/vue';\nimport { controlApi, why, type TlsRedeploy, type TlsStatus } from '../../api-control';\nimport { daysLeft } from '../../lib/control';\nimport { stamp } from '../../format';\nimport { toast } from '../../state';\n\nconst props = defineProps<{ tls: TlsStatus; canAdmin: boolean }>();\nconst emit = defineEmits<{ reload: [] }>();\n\nconst cert = ref('');\nconst key = ref('');\nconst storing = ref(false);\nconst removing = ref(false);\nconst confirmRemove = ref(false);\nconst redeploying = ref(false);\nconst redeployed = ref<TlsRedeploy | null>(null);\n\nconst days = computed(() => (props.tls.wildcard ? daysLeft(props.tls.wildcard.notAfter) : null));\nconst items = computed(() => {\n const w = props.tls.wildcard;\n if (!w) return [];\n return [\n { key: 'covers', label: 'Covers', value: w.domains.join(', ') },\n { key: 'until', label: 'Valid until', value: stamp(w.notAfter) },\n { key: 'issuer', label: 'Issuer', value: w.issuer || 'unnamed' },\n ];\n});\n\nasync function store(): Promise<void> {\n storing.value = true;\n const r = await controlApi.storeWildcard(cert.value, key.value);\n storing.value = false;\n if (!r.ok) {\n toast(why(r, 'Store the wildcard'), 'danger');\n return;\n }\n cert.value = key.value = '';\n redeployed.value = null;\n toast('Stored. Redeploy all stacks.', 'success');\n emit('reload');\n}\nasync function remove(): Promise<void> {\n removing.value = true;\n const r = await controlApi.removeWildcard();\n removing.value = false;\n confirmRemove.value = false;\n if (!r.ok) {\n toast(why(r, 'Remove the wildcard'), 'danger');\n return;\n }\n redeployed.value = null;\n toast('Removed. Redeploy all stacks.', 'success');\n emit('reload');\n}\nasync function redeploy(): Promise<void> {\n redeploying.value = true;\n const r = await controlApi.redeploy();\n redeploying.value = false;\n if (!r.ok) {\n toast(why(r, 'Redeploy the stacks'), 'danger');\n return;\n }\n redeployed.value = r.body;\n toast(`Redeploying ${r.body.started.length}, skipped ${r.body.skipped.length}.`, 'success');\n}\n</script>\n\n<template>\n <HCard title=\"Certificates\">\n <HStack :gap=\"4\" direction=\"column\">\n <HStack direction=\"row\" :gap=\"2\" wrap align=\"center\">\n <HBadge :tone=\"tls.mode === 'dns-persist-01' ? 'success' : 'info'\" :label=\"tls.mode\" />\n <HBadge v-if=\"days !== null\" :tone=\"days < 21 ? 'danger' : 'neutral'\" :label=\"`${days} days left`\" />\n <HBadge v-if=\"tls.wildcard?.selfSigned\" tone=\"warning\" label=\"Self-signed\" />\n </HStack>\n <HDescriptionList v-if=\"items.length\" :items=\"items\" variant=\"inline\" />\n <HAlert v-if=\"tls.wildcard?.selfSigned\" tone=\"warning\" title=\"Browsers will warn.\" compact />\n <HStack direction=\"row\" v-if=\"tls.wildcard && canAdmin\" :gap=\"3\" align=\"center\" wrap>\n <HButton variant=\"danger\" :loading=\"removing\" @click=\"confirmRemove = true\">Remove wildcard</HButton>\n <HText tone=\"muted\">Stacks under it serve no certificate until redeployed.</HText>\n </HStack>\n\n <template v-if=\"canAdmin\">\n <HTextarea v-model=\"cert\" label=\"Certificate (PEM, leaf first)\" :rows=\"5\" placeholder=\"-----BEGIN CERTIFICATE-----\" hint=\"Stored 0600. Never returned.\" />\n <HTextarea v-model=\"key\" label=\"Private key (PEM)\" :rows=\"4\" placeholder=\"-----BEGIN PRIVATE KEY-----\" />\n <div>\n <HButton variant=\"primary\" :loading=\"storing\" :disabled=\"!cert.trim() || !key.trim()\" @click=\"store\">\n {{ tls.wildcard ? 'Replace wildcard' : 'Store wildcard' }}\n </HButton>\n </div>\n </template>\n <HText v-else-if=\"!tls.wildcard\" tone=\"muted\">Admin only.</HText>\n\n <HStack direction=\"row\" :gap=\"3\" align=\"center\" wrap>\n <HButton :loading=\"redeploying\" @click=\"redeploy\">Redeploy all stacks</HButton>\n <HText tone=\"muted\">Asleep stacks pick up new labels on wake.</HText>\n </HStack>\n <HAlert\n v-if=\"redeployed\"\n tone=\"info\"\n :title=\"`Started ${redeployed.started.length}, skipped ${redeployed.skipped.length}`\"\n :description=\"redeployed.skipped.map((x) => `${x.id}: ${x.reason}`).join('; ') || undefined\"\n compact\n />\n </HStack>\n <HAlertDialog\n v-model:open=\"confirmRemove\"\n danger\n title=\"Remove the wildcard?\"\n description=\"Deployed stacks lose TLS.\"\n confirm-label=\"Remove\"\n :busy=\"removing\"\n @confirm=\"remove\"\n />\n </HCard>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { HAlertDialog, HButton, HCard, HInput, HList, HListItem, HStack, HText } from '@hearth-ui/vue';\nimport { controlApi, why, type DomainsStatus } from '../../api-control';\nimport { domainProblem } from '../../lib/control';\nimport { toast } from '../../state';\n\nconst props = defineProps<{ domains: DomainsStatus; canEdit: boolean }>();\nconst emit = defineEmits<{ reload: [] }>();\n\nconst next = ref('');\nconst busy = ref(false);\nconst removing = ref('');\nconst problem = computed(() => (next.value ? domainProblem(next.value, props.domains.domains, props.domains.primary) : ''));\n\n/** The list replaces what is stored, so add and remove are the same call. */\nasync function save(list: string[]): Promise<boolean> {\n busy.value = true;\n const r = await controlApi.saveDomains(list);\n busy.value = false;\n if (!r.ok) {\n toast(why(r, 'Save the domains'), 'danger');\n return false;\n }\n toast('Domains saved.', 'success');\n emit('reload');\n return true;\n}\nasync function add(): Promise<void> {\n if (problem.value || !next.value.trim()) return;\n if (await save([...props.domains.domains, next.value.trim().toLowerCase()])) next.value = '';\n}\nasync function remove(): Promise<void> {\n const d = removing.value;\n await save(props.domains.domains.filter((x) => x !== d));\n removing.value = '';\n}\n</script>\n\n<template>\n <HCard title=\"Domains\">\n <HStack :gap=\"3\" direction=\"column\">\n <HList label=\"Domains\">\n <HListItem :title=\"domains.primary || 'Not set'\" description=\"Primary\" />\n <HListItem v-for=\"d in domains.domains\" :key=\"d\" :title=\"d\" :description=\"`control.${d} · api.${d}`\">\n <template v-if=\"canEdit\" #trailing>\n <HButton variant=\"ghost\" size=\"compact\" :label=\"`Remove ${d}`\" :disabled=\"busy\" @click=\"removing = d\">Remove</HButton>\n </template>\n </HListItem>\n </HList>\n <HStack direction=\"row\" v-if=\"canEdit\" :gap=\"3\" wrap align=\"end\">\n <HInput v-model=\"next\" label=\"Add a domain\" placeholder=\"preview.example.com\" :error=\"problem\" @keyup.enter=\"add\" />\n <HButton variant=\"primary\" :loading=\"busy\" :disabled=\"!next.trim() || !!problem\" @click=\"add\">Add</HButton>\n </HStack>\n <HText v-else tone=\"muted\">Maintainer only.</HText>\n </HStack>\n <HAlertDialog\n :open=\"!!removing\"\n danger\n :title=\"`Remove ${removing}?`\"\n confirm-label=\"Remove\"\n :busy=\"busy\"\n @update:open=\"(o: boolean) => !o && (removing = '')\"\n @confirm=\"remove\"\n />\n </HCard>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue';\nimport { RouterLink } from 'vue-router';\nimport { HAlert, HAlertDialog, HBadge, HButton, HCard, HInput, HNumberInput, HSelect, HSettingsPage, HStack, HSwitch, HText } from '@hearth-ui/vue';\nimport type { Job, LokiSettings, LokiStorageInput } from '@samyx/preview-stacks-client';\nimport { controlApi, id, poll, why } from '../../api-control';\nimport { isTerminal, rangeProblem, storageBadge, supersededBy } from '../../lib/control';\nimport { data, toast } from '../../state';\n\nconst props = defineProps<{ canAdmin: boolean }>();\n\nconst logging = ref<LokiSettings | null>(null);\nconst loaded = ref(false);\nconst loadError = ref('');\nconst saveError = ref('');\nconst saving = ref(false);\n/** The apply job a save started, or the one that superseded it, until it ends. */\nconst applying = ref<string | null>(null);\n\ntype Chunks = { retentionDays: number | null; idlePeriodMinutes: number | null; maxAgeMinutes: number | null; targetSizeKiB: number | null; encoding: string };\nconst blank = (): Chunks => ({ retentionDays: null, idlePeriodMinutes: null, maxAgeMinutes: null, targetSizeKiB: null, encoding: '' });\nconst draft = ref<Chunks>(blank());\nconst saved = ref<Chunks>(blank());\nconst s3 = ref({ endpoint: '', region: '', bucket: '', pathStyle: false, accessKeyId: '' });\nconst secret = ref('');\nconst wantS3 = ref(false);\nconst confirmS3 = ref(false);\n\n// Refill only when the SAVED values change: the poll must not wipe typing.\nwatch(\n () => logging.value && JSON.stringify([logging.value.retentionDays, logging.value.chunks, logging.value.storage]),\n () => {\n const l = logging.value;\n if (!l) return;\n saved.value = { retentionDays: l.retentionDays, ...l.chunks };\n draft.value = { ...saved.value };\n wantS3.value = l.storage.type === 's3';\n const x = l.storage.s3;\n s3.value = { endpoint: x?.endpoint ?? '', region: x?.region ?? '', bucket: x?.bucket ?? '', pathStyle: x?.pathStyle ?? false, accessKeyId: x?.accessKeyId ?? '' };\n },\n);\n\nconst onS3 = computed(() => logging.value?.storage.type === 's3');\n/** S3 is one-way and fixed once saved. */\nconst storageLocked = computed(() => onS3.value || !props.canAdmin);\nconst dirty = computed(() => JSON.stringify(draft.value) !== JSON.stringify(saved.value));\nconst lim = computed(() => logging.value?.limits);\nconst problems = computed(() => {\n const l = lim.value;\n if (!l) return {};\n const d = draft.value;\n return {\n retentionDays: rangeProblem(d.retentionDays, l.retentionDays),\n idlePeriodMinutes: rangeProblem(d.idlePeriodMinutes, l.idlePeriodMinutes),\n maxAgeMinutes: rangeProblem(d.maxAgeMinutes, l.maxAgeMinutes),\n targetSizeKiB: rangeProblem(d.targetSizeKiB, l.targetSizeKiB),\n };\n});\nconst valid = computed(() => Object.values(problems.value).every((p) => !p) && !!draft.value.encoding);\nconst encodings = computed(() => (lim.value?.encodings ?? []).map((e) => ({ value: e, label: e })));\nconst s3Ready = computed(() => !!(s3.value.endpoint.trim() && s3.value.region.trim() && s3.value.bucket.trim() && s3.value.accessKeyId.trim() && (onS3.value || secret.value)));\n\n/** One read of the followed job: keep following, follow its successor, or end with a toast. */\nasync function follow(jobId: string): Promise<void> {\n const r = await controlApi.job(jobId);\n if (applying.value !== jobId) return; // a newer save took over during the read\n if (r.status === 404) {\n applying.value = null;\n return;\n }\n if (!r.ok || !isTerminal(r.body.job.state)) return;\n const job: Job = r.body.job;\n if (job.state === 'superseded') {\n applying.value = supersededBy(job, data.jobs)?.id ?? jobId; // the successor carries this save\n return;\n }\n applying.value = null;\n if (job.state === 'ok') toast('Applied.', 'success');\n else if (job.state === 'cancelled') toast('Cancelled.', 'warning');\n else toast('Apply failed.', 'danger', `Job ${job.id}`);\n}\n\nasync function load(): Promise<void> {\n if (applying.value) await follow(applying.value);\n const r = await controlApi.logging();\n loaded.value = true;\n if (r.ok) {\n logging.value = r.body;\n loadError.value = '';\n } else if (r.status !== 403) loadError.value = why(r, 'Read the logging settings');\n else loadError.value = 'Maintainer only.';\n}\npoll(load, 10_000);\n\nasync function save(r: ReturnType<typeof controlApi.saveLogging>): Promise<void> {\n saving.value = true;\n const res = await r;\n saving.value = false;\n if (!res.ok) {\n saveError.value = why(res, 'Save');\n return;\n }\n saveError.value = '';\n secret.value = '';\n if ('job' in res.body) {\n applying.value = res.body.job.id;\n toast('Applying.', 'info');\n } else toast('No change.', 'success');\n await load();\n}\n\nconst saveChunks = () => {\n const d = draft.value;\n return save(\n controlApi.saveLogging({\n retentionDays: d.retentionDays,\n chunks: { idlePeriodMinutes: d.idlePeriodMinutes, maxAgeMinutes: d.maxAgeMinutes, targetSizeKiB: d.targetSizeKiB, encoding: d.encoding },\n }),\n );\n};\nconst reset = () => (draft.value = { ...saved.value });\nfunction saveStorage(): Promise<void> {\n const l = logging.value;\n if (!l) return Promise.resolve();\n const body: LokiStorageInput = {\n type: 's3',\n ...s3.value,\n secretAccessKey: secret.value, // '' keeps the stored secret\n cutover: l.storage.s3?.cutover ?? l.limits.earliestCutover,\n };\n confirmS3.value = false;\n return save(controlApi.saveStorage(body));\n}\n</script>\n\n<template>\n <!-- Hidden when this host runs no Loki. -->\n <HCard v-if=\"!loaded || loadError || (logging && logging.enabled !== false)\" title=\"Logging\">\n <HAlert v-if=\"loadError\" tone=\"danger\" :title=\"loadError\" compact />\n <HText v-else-if=\"!logging\" tone=\"muted\">Loading.</HText>\n <HAlert v-else-if=\"logging.enabled === null\" tone=\"warning\" title=\"Docker did not answer.\" compact />\n <HStack v-else :gap=\"4\" direction=\"column\">\n <HStack direction=\"row\" :gap=\"2\" align=\"center\" wrap>\n <HBadge tone=\"info\" :label=\"storageBadge(logging.storage.s3)\" />\n <RouterLink v-if=\"applying\" :to=\"`/jobs/${id(applying)}`\"><HBadge tone=\"info\" label=\"Applying\" dot /></RouterLink>\n </HStack>\n\n <HSettingsPage\n class=\"chunks\"\n title=\"Retention and chunks\"\n description=\"Restarts Loki.\"\n :dirty=\"dirty\"\n :saving=\"saving\"\n :error=\"saveError || (dirty && !valid ? 'Fix the highlighted fields.' : '')\"\n @save=\"valid ? saveChunks() : (saveError = 'Fix the highlighted fields.')\"\n @reset=\"reset\"\n >\n <HStack :gap=\"3\" direction=\"column\">\n <HNumberInput v-model=\"draft.retentionDays\" label=\"Retention (days)\" :min=\"lim!.retentionDays.min\" :max=\"lim!.retentionDays.max\" :error=\"problems.retentionDays\" />\n <HNumberInput v-model=\"draft.idlePeriodMinutes\" label=\"Chunk idle (min)\" :min=\"lim!.idlePeriodMinutes.min\" :max=\"lim!.idlePeriodMinutes.max\" :error=\"problems.idlePeriodMinutes\" />\n <HNumberInput v-model=\"draft.maxAgeMinutes\" label=\"Chunk max age (min)\" :min=\"lim!.maxAgeMinutes.min\" :max=\"lim!.maxAgeMinutes.max\" :error=\"problems.maxAgeMinutes\" />\n <HNumberInput v-model=\"draft.targetSizeKiB\" label=\"Chunk size (KiB)\" :min=\"lim!.targetSizeKiB.min\" :max=\"lim!.targetSizeKiB.max\" :error=\"problems.targetSizeKiB\" />\n <HSelect v-model=\"draft.encoding\" label=\"Encoding\" :options=\"encodings\" />\n </HStack>\n </HSettingsPage>\n\n <HCard title=\"Storage\" :description=\"storageLocked ? (canAdmin ? 'Fixed once saved.' : 'Admin only.') : 'One-way.'\">\n <HStack :gap=\"3\" direction=\"column\">\n <HSwitch v-model=\"wantS3\" label=\"S3\" :disabled=\"storageLocked\" />\n <template v-if=\"wantS3\">\n <HInput v-model=\"s3.endpoint\" type=\"url\" label=\"Endpoint\" :disabled=\"storageLocked\" />\n <HInput v-model=\"s3.region\" label=\"Region\" :disabled=\"storageLocked\" />\n <HInput v-model=\"s3.bucket\" label=\"Bucket\" :disabled=\"storageLocked\" />\n <HSwitch v-model=\"s3.pathStyle\" label=\"Path-style\" :disabled=\"storageLocked\" />\n <HInput v-model=\"s3.accessKeyId\" label=\"Access key ID\" autocomplete=\"off\" :disabled=\"!canAdmin\" />\n <HInput\n v-if=\"canAdmin\"\n v-model=\"secret\"\n type=\"password\"\n label=\"Secret access key\"\n autocomplete=\"new-password\"\n :hint=\"logging.storage.s3?.secretSet ? 'Write-only. Leave empty to keep.' : 'Write-only.'\"\n />\n <div v-if=\"canAdmin\">\n <HButton v-if=\"onS3\" :loading=\"saving\" :disabled=\"!s3Ready\" @click=\"saveStorage\">Save keys</HButton>\n <HButton v-else :loading=\"saving\" :disabled=\"!s3Ready\" @click=\"confirmS3 = true\">Switch to S3</HButton>\n </div>\n </template>\n </HStack>\n <HAlertDialog\n v-model:open=\"confirmS3\"\n danger\n :title=\"`Switch to S3 from ${logging.limits.earliestCutover} UTC?`\"\n description=\"One-way.\"\n confirm-label=\"Switch to S3\"\n :busy=\"saving\"\n @confirm=\"saveStorage\"\n />\n </HCard>\n </HStack>\n </HCard>\n</template>\n\n<style scoped>\n/* Hearth sizes a settings page title as a page heading; inside a card it is a section. */\n.chunks :deep(h1) { font-size: 1.125rem; line-height: 1.4; }\n</style>\n","<script setup lang=\"ts\">\n/**\n * The control stack as an operator debugs it. Restarts and OOM lead because a restarting Traefik\n * loses in-flight certificate issuance while every container still reads `running`.\n */\nimport { computed, ref } from 'vue';\nimport { HAlert, HButton, HPageHeader, HStack, HStatCard } from '@hearth-ui/vue';\nimport { controlApi, poll, why, type ControlRuntime, type DomainsStatus, type TlsStatus } from '../api-control';\nimport { atLeast, daysLeft, type RoleName } from '../lib/control';\nimport { auth } from '../state';\nimport ContainersCard from './control/ContainersCard.vue';\nimport CertificatesCard from './control/CertificatesCard.vue';\nimport DomainsCard from './control/DomainsCard.vue';\nimport LoggingCard from './control/LoggingCard.vue';\n\nconst can = (min: RoleName) => atLeast(auth.root, auth.role, min);\n\nconst runtime = ref<ControlRuntime | null>(null);\nconst loaded = ref(false);\nconst error = ref('');\nconst forbidden = ref(false);\nconst domains = ref<DomainsStatus | null>(null);\nconst tls = ref<TlsStatus | null>(null);\n\nasync function loadRuntime(): Promise<void> {\n // Below maintainer every call here is a 403: say so without asking (and without logging one every poll).\n if (!can('maintainer')) {\n loaded.value = forbidden.value = true;\n return;\n }\n const r = await controlApi.runtime();\n loaded.value = true;\n forbidden.value = r.status === 403;\n if (!r.ok) {\n error.value = forbidden.value ? '' : why(r, 'Read the control stack');\n return;\n }\n error.value = '';\n runtime.value = { ...r.body, containers: r.body.containers ?? [] };\n}\nasync function loadDomains(): Promise<void> {\n if (!can('maintainer')) return;\n const r = await controlApi.domains();\n if (r.ok) domains.value = { ...r.body, domains: r.body.domains ?? [] };\n}\nasync function loadTls(): Promise<void> {\n if (!can('maintainer')) return;\n const r = await controlApi.tls();\n if (r.ok) tls.value = r.body;\n}\nconst reloadDomains = () => Promise.all([loadDomains(), loadTls()]);\nconst refreshing = ref(false);\nasync function reloadAll(): Promise<void> {\n refreshing.value = true;\n await Promise.all([loadRuntime(), loadDomains(), loadTls()]);\n refreshing.value = false;\n}\npoll(loadRuntime, 10_000);\npoll(loadDomains, 30_000);\npoll(loadTls, 30_000);\n\nconst restarts = computed(() => (runtime.value?.containers ?? []).reduce((n, c) => n + c.restartCount, 0));\nconst oomed = computed(() => (runtime.value?.containers ?? []).filter((c) => c.oomKilled).length);\nconst days = computed(() => (tls.value?.wildcard ? daysLeft(tls.value.wildcard.notAfter) : null));\n// The primary is only there once init has set one, so it is counted rather than assumed.\nconst domainCount = computed(() => (domains.value ? domains.value.domains.length + (domains.value.primary ? 1 : 0) : 0));\n</script>\n\n<template>\n <HStack :gap=\"4\" direction=\"column\">\n <HPageHeader title=\"Control stack\" eyebrow=\"Host\" description=\"Containers, hostnames, certificates and logging.\" actions-placement=\"end\">\n <template #actions>\n <HButton variant=\"secondary\" icon=\"arrow\" label=\"Refresh\" :loading=\"refreshing\" @click=\"reloadAll\" />\n </template>\n </HPageHeader>\n\n <HAlert v-if=\"forbidden\" tone=\"warning\" title=\"Maintainer only.\" />\n <template v-else>\n <HStack direction=\"row\" v-if=\"runtime?.reachable\" :gap=\"3\" wrap>\n <HStatCard label=\"Restarts\" :value=\"restarts\" :tone=\"restarts ? 'warning' : 'neutral'\" />\n <HStatCard label=\"OOM killed\" :value=\"oomed\" :tone=\"oomed ? 'danger' : 'neutral'\" />\n <HStatCard v-if=\"tls\" label=\"Certificates\" :value=\"tls.mode\" />\n <HStatCard v-if=\"days !== null\" label=\"Cert expires\" :value=\"`${days}d`\" :tone=\"days < 21 ? 'danger' : 'neutral'\" />\n <HStatCard v-if=\"domainCount\" label=\"Domains\" :value=\"domainCount\" />\n </HStack>\n\n <ContainersCard :runtime=\"runtime\" :loaded=\"loaded\" :error=\"error\" :can-restart=\"can('maintainer')\" @reload=\"loadRuntime\" />\n <DomainsCard v-if=\"domains\" :domains=\"domains\" :can-edit=\"can('maintainer')\" @reload=\"reloadDomains\" />\n <CertificatesCard v-if=\"tls\" :tls=\"tls\" :can-admin=\"can('admin')\" @reload=\"loadTls\" />\n <LoggingCard v-if=\"can('maintainer')\" :can-admin=\"can('admin')\" />\n </template>\n </HStack>\n</template>\n"],"names":["ROLES","atLeast","root","role","min","have","mem","bytes","daysLeft","notAfter","now","storageBadge","s3","today","domainProblem","raw","existing","primary","d","rangeProblem","v","r","supersededBy","job","jobs","i","j","isTerminal","state","props","__props","emit","__emit","columns","list","computed","_a","named","byLabel","c","rows","rid","ago","find","rowId","rowActions","row","confirm","ref","busy","onAction","e","restart","service","controlApi","toast","why","_createBlock","_unref","HCard","HAlert","HDataTable","column","value","_createElementBlock","_Fragment","_createTextVNode","_toDisplayString","HBadge","containerTone","_b","_c","_createVNode","_d","HEmptyState","HSkeleton","HAlertDialog","_cache","$event","cert","key","storing","removing","confirmRemove","redeploying","redeployed","days","items","w","stamp","store","remove","redeploy","HStack","HDescriptionList","HButton","HText","HTextarea","_createElementVNode","x","next","problem","save","add","HList","HListItem","_openBlock","_renderList","HInput","o","logging","loaded","loadError","saveError","saving","applying","blank","draft","saved","secret","wantS3","confirmS3","watch","l","onS3","storageLocked","dirty","lim","problems","valid","p","encodings","s3Ready","follow","jobId","data","load","poll","res","saveChunks","reset","saveStorage","body","RouterLink","id","HSettingsPage","HNumberInput","HSelect","HSwitch","_hoisted_1","can","auth","runtime","error","forbidden","domains","tls","loadRuntime","loadDomains","loadTls","reloadDomains","refreshing","reloadAll","restarts","n","oomed","domainCount","HPageHeader","HStatCard","ContainersCard","DomainsCard","CertificatesCard","LoggingCard"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ .chunks[data-v-83888201] h1{font-size:1.125rem;line-height:1.4}
@@ -0,0 +1,32 @@
1
+ .wrap[data-v-c749235a]{overflow-wrap:anywhere}/**
2
+ * Copyright (c) 2014 The xterm.js authors. All rights reserved.
3
+ * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
4
+ * https://github.com/chjj/term.js
5
+ * @license MIT
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ *
25
+ * Originally forked from (with the author's permission):
26
+ * Fabrice Bellard's javascript vt100 for jslinux:
27
+ * http://bellard.org/jslinux/
28
+ * Copyright (c) 2011 Fabrice Bellard
29
+ * The original design remains. The terminal itself
30
+ * has been extended to include xterm CSI codes, among
31
+ * other features.
32
+ */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.term[data-v-fe2ef41e]{min-height:26rem;max-width:100%;padding:.5rem;overflow:hidden;background:#0b0e14;border:1px solid var(--h-border);border-radius:var(--h-radius-control)}
@@ -0,0 +1,4 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/xterm-D6Mng-DB.js","assets/_commonjsHelpers-CqkleIqs.js","assets/addon-fit-CevVMrUA.js"])))=>i.map(i=>d[i]);
2
+ import{b as ne,M as _,z as ve,C as pe,D as fe,A as C,r as A,k as me,d as Z,O as Q,c as o,u as e,B as Y,w as n,Z as le,g as W,N as O,f as a,m as te,h as z,i as ae,F as M,l as J,n as w,t as q,j as b,Q as B,e as t,x as L,U as $e,$ as Se,a0 as Ue,a1 as ue,V as ee,a2 as De,S as Ie,G as re,J as Re,K as Te,q as oe,W as qe,Y as Ee,_ as Ne,a as xe,a3 as ze,a4 as Be,a5 as ye,a6 as be,a7 as Fe,a8 as Pe,a9 as We}from"./index-Cthapg0Q.js";import{d as X,s as Ke,t as He,r as de}from"./api-deployment-HPEzQSZD.js";import{A as Le,a as ke,j as Me,t as Je}from"./format-Dr8IZDXn.js";import{a as G,w as Ye,c as Qe,b as Ze,S as Ge,d as Xe,u as _e,M as he,f as et,e as tt,p as nt,l as lt,g as Ve,s as se,h as we,t as at,i as Ce,j as ot,k as it,r as rt,m as st,n as ut}from"./use-logs-BD6ml1rA.js";import{d as P,u as ie,r as Ae,o as ge,V as dt,p as ct,a as vt}from"./VarEditor-DYmuml3i.js";import{c as mt,v as ce}from"./vars-C8sghQal.js";import{_ as Oe}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{b as pt}from"./labels-wffzJI2t.js";import"./problem-Cs7tz86T.js";import"./varformats-DSwvKZLe.js";function ft(u,f){const p=ne(),m=A(""),v=A(""),$=A(null),g=A(""),U=C(()=>{var r;return((r=f.value)==null?void 0:r.busy)===!0}),S=(r,c=!1)=>pe("developer",fe)?Ye(r,f.value,c):"Needs the developer role.";function h(){m.value="",v.value="",$.value=null,g.value=""}function k(r){var F,x;const c=Qe(r);$.value=c;const R=c.stack||((F=f.value)==null?void 0:F.stack);g.value=c.kind==="other"&&R?((x=me.jobs.find(K=>K.state==="running"&&K.stack===R))==null?void 0:x.id)??"":""}async function D(r,c={}){if(!f.value)return;const R=r==="down"&&!!c.forget,F=R?"Tear down and forget":Le[r];m.value=R?"down-forget":r,v.value="",$.value=null;const x=await X.act(u(),r,c);if(m.value="",x.status===202){const K=x.body.job;if(!(K!=null&&K.id)){v.value="Started, but there is no job to follow. Check Jobs.";return}_(`${F} ${K.state==="queued"?"queued":"started"}`,"success",K.stack),ve(),p.push(`/jobs/${encodeURIComponent(K.id)}`);return}if(x.status===409)return k(x.body);v.value=G(x.status,x.body.error,F),_(`${F} refused`,"danger",v.value)}async function E(){m.value="forget",v.value="",$.value=null;const r=await X.forget(u());if(m.value="",r.ok){_("Forgotten","success",u()),ve(),p.push("/deployments");return}if(r.status===409)return k(r.body);v.value=G(r.status,r.body.error,"Forget")}return{pending:m,error:v,conflict:$,conflictJobId:g,busy:U,why:S,reset:h,act:D,forgetRecord:E}}const gt=Z({__name:"AxesTab",props:{id:{},dep:{},runtime:{}},setup(u){const f=u;Q(()=>f.id,ge,{immediate:!0});const p=["up","assert_live","down","assert_gone"],m=[{key:"name",label:"Axis",sortable:!0},{key:"hooks",label:"Hooks"},{key:"verifiable",label:"Teardown provable"}],v=C(()=>{var $;return((($=P.data)==null?void 0:$.axes)??[]).map(g=>({id:g.name,name:g.name,hooks:g.hooks,verifiable:g.verifiable}))});return($,g)=>(t(),o(e(Y),{title:"Axes"},{footer:n(()=>[a(e(B),{variant:"secondary",icon:"arrow",label:"Re-resolve",loading:e(P).loading,onClick:e(Ae)},null,8,["loading","onClick"])]),default:n(()=>[e(P).loading&&!e(P).data&&!e(P).error?(t(),o(e(le),{key:0,variant:"text",lines:3,label:"Loading axes"})):e(P).error?(t(),o(e(W),{key:1,tone:"danger",title:"Spec did not resolve",description:e(P).error},null,8,["description"])):(t(),o(e(O),{key:2,direction:"column",gap:3},{default:n(()=>[a(e(te),{rows:v.value,columns:m,label:"Axes","empty-text":"No axes."},{cell:n(({row:U,column:S,value:h})=>[S.key==="hooks"?(t(),o(e(O),{key:0,direction:"row",gap:1,wrap:""},{default:n(()=>[(t(),z(M,null,ae(p,k=>a(e(J),{key:k,size:"sm",label:U.hooks.includes(k)?k:`${k} (none)`,variant:U.hooks.includes(k)?"soft":"dashed"},null,8,["label","variant"])),64))]),_:2},1024)):S.key==="verifiable"?(t(),o(e(J),{key:1,tone:h?"success":"warning",label:h?"assert_gone":"Unverifiable"},null,8,["tone","label"])):(t(),z(M,{key:2},[w(q(h),1)],64))]),_:1},8,["rows"]),e(ie).length?(t(),o(e(W),{key:0,tone:"warning",title:`${e(ie).length===1?"1 axis cannot":`${e(ie).length} axes cannot`} be verified: ${e(ie).join(", ")}`},null,8,["title"])):b("",!0)]),_:1}))]),_:1}))}}),yt={key:2},bt={key:3,class:"wrap"},kt=Z({__name:"ConfigTab",props:{id:{},dep:{},runtime:{}},setup(u){const f=u;Q(()=>f.id,ge,{immediate:!0});const p=C(()=>{var S;return(S=f.dep)==null?void 0:S.vars}),m=C(()=>Object.entries(p.value??{}).map(([S,h])=>({key:S,label:S,value:h}))),v=C(()=>mt(P.vars,p.value)),$=C(()=>P.vars.filter(S=>S.k).length),g=[{key:"key",label:"Key",sortable:!0},{key:"value",label:"Value"},{key:"visibility",label:"Visibility",hideBelow:420},{key:"length",label:"Length (chars)",align:"end",hideBelow:520}],U=C(()=>{var S;return(((S=P.data)==null?void 0:S.env)??[]).map(h=>({...h,id:h.key}))});return(S,h)=>(t(),o(e(O),{direction:"column",gap:4},{default:n(()=>[a(e(Y),{title:"Request variables",description:"Per browser."},{default:n(()=>[a(e(O),{direction:"column",gap:3},{default:n(()=>[a(dt,{modelValue:e(P).vars,"onUpdate:modelValue":h[0]||(h[0]=k=>e(P).vars=k),onChange:e(ct)},null,8,["modelValue","onChange"]),a(e(O),{direction:"row",gap:3,align:"center",wrap:""},{default:n(()=>[a(e(B),{variant:"primary",loading:e(P).loading,onClick:e(vt)},{default:n(()=>[...h[1]||(h[1]=[w("Apply and reload",-1)])]),_:1},8,["loading","onClick"]),a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[w(q($.value?`${$.value} variable${$.value===1?"":"s"}`:"No variables"),1)]),_:1})]),_:1})]),_:1})]),_:1}),m.value.length?(t(),o(e(Y),{key:0,title:"Stored on the server",description:"Request variables override these."},{default:n(()=>[a(e(O),{direction:"column",gap:3},{default:n(()=>[a(e($e),{items:m.value,variant:"inline",dense:""},null,8,["items"]),v.value.length?(t(),o(e(W),{key:0,tone:"warning",title:`Overridden: ${v.value.join(", ")}`,description:"Stacks differ."},null,8,["title"])):b("",!0)]),_:1})]),_:1})):b("",!0),a(e(Y),{title:"Declared env",description:"After interpolation."},{default:n(()=>[e(P).loading&&!e(P).data&&!e(P).error?(t(),o(e(le),{key:0,variant:"text",lines:4,label:"Loading env"})):e(P).error?(t(),o(e(W),{key:1,tone:"danger",title:"Spec did not resolve",description:e(P).error},null,8,["description"])):(t(),o(e(O),{key:2,direction:"column",gap:3},{default:n(()=>[a(e(te),{rows:U.value,columns:g,label:"Declared env","empty-text":"No env block.","page-size":25},{cell:n(({row:k,column:D,value:E})=>[D.key==="visibility"?(t(),o(e(J),{key:0,tone:E==="masked"?"warning":"neutral",label:String(E)},null,8,["tone","label"])):D.key==="length"?(t(),z(M,{key:1},[w(q(E)+" ",1),E===0?(t(),o(e(J),{key:0,tone:"warning",label:"Never set"})):b("",!0)],64)):D.key==="value"&&k.visibility==="masked"?(t(),z("code",yt,q(E),1)):D.key==="value"?(t(),z("span",bt,q(E),1)):(t(),z(M,{key:4},[w(q(E),1)],64))]),_:1},8,["rows"]),a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[...h[2]||(h[2]=[w("Masked values are never sent to this page.",-1)])]),_:1})]),_:1}))]),_:1})]),_:1}))}}),ht=Oe(kt,[["__scopeId","data-v-c749235a"]]),je=Z({__name:"ConflictNote",props:{conflict:{},jobId:{}},setup(u){const f=u,p=ne(),m=C(()=>{const v=f.conflict;return v.kind==="shared"?"Type the stack name and tear down again.":v.kind==="containers"?"Tear down first. Forgetting now would orphan those containers.":v.kind==="referenced"?`Still used by ${v.deployments.join(", ")}.`:f.jobId?"":"Nothing was retried. Wait for the current work to finish."});return(v,$)=>(t(),o(e(W),{tone:u.conflict.kind==="shared"?"warning":"info",title:"Refused. Nothing was started.",description:[u.conflict.text,m.value].filter(Boolean).join(" ")},{default:n(()=>[u.jobId?(t(),o(e(B),{key:0,variant:"ghost",label:"Follow the running job","trailing-icon":"right",onClick:$[0]||($[0]=g=>e(p).push(`/jobs/${encodeURIComponent(u.jobId)}`))})):b("",!0)]),_:1},8,["tone","description"]))}}),wt=Z({__name:"EquivalentCommand",props:{method:{},path:{},body:{}},setup(u){const f=u,p=A(!1),m=C(()=>Ze(`${location.protocol}//${location.host}`,f.method,f.path,f.body));return(v,$)=>(t(),z(M,null,[a(e(B),{variant:"ghost",icon:"code",label:"Equivalent command",onClick:$[0]||($[0]=g=>p.value=!0)}),a(e(Se),{open:p.value,title:"Equivalent command",description:"$PSTACK_TOKEN stays a variable.",onClose:$[1]||($[1]=g=>p.value=!1)},{default:n(()=>[a(e(Ue),{code:m.value,language:"bash",title:"curl",wrap:""},null,8,["code"])]),_:1},8,["open"])],64))}}),Ct=Z({__name:"DeploymentDanger",props:{id:{},dep:{},actions:{}},setup(u){const f=u,p=f.actions,m=C(()=>{var s;return((s=f.dep)==null?void 0:s.kind)==="shared"}),v=C(()=>{var s;return((s=f.dep)==null?void 0:s.stack)??""}),$=C(()=>p.why("sleep")),g=A(!0),U=A(!0),S=A("7d"),h=A(null),k=A(""),D=A(!1),E=C(()=>Xe(g.value,U.value));async function r(){D.value=!0,k.value="",h.value=null;const s=await X.share(f.id,E.value,S.value);D.value=!1,s.status===201?h.value=s.body:k.value=G(s.status,s.body.error,"Share link")}const c=A(!0),R=A(""),F=C(()=>!!v.value&&R.value===v.value),x=C(()=>p.why("down",F.value)),K=A(!1),N=A(!1);async function T(){N.value=!0;const s=await X.cancel(f.id);if(N.value=!1,!s.ok){_("Stop refused","danger",G(s.status,s.body.error,"Stop"));return}const l=s.body.cancelled.length;_(l?`Stopped ${l} job${l>1?"s":""}`:"Nothing was running or queued",l?"success":"info"),K.value=s.body.cancelled.some(i=>i.state==="running"),ve()}const I=Te({open:!1,kind:"down"}),y={down:{title:"Tear down",text:"Containers, networks and volumes are removed.",confirm:"Tear down"},"down-forget":{title:"Tear down and forget",text:"Tears down, then removes the record if nothing is left behind.",confirm:"Tear down and forget"},stop:{title:"Stop everything on this stack",text:"Cancels the running job and the one queued behind it. Nothing is undone.",confirm:"Stop everything"},forget:{title:"Forget this deployment",text:"Removes the record only. Containers are not touched.",confirm:"Forget"}};function V(s){I.kind=s,I.open=!0}function d(){I.open=!1;const s=m.value&&F.value;I.kind==="down"?p.act("down",{verify:c.value,force:s}):I.kind==="down-forget"?p.act("down",{verify:!0,force:s,forget:!0}):I.kind==="stop"?T():p.forgetRecord()}return Q(()=>f.id,()=>{h.value=null,k.value="",R.value="",K.value=!1}),(s,l)=>(t(),o(e(O),{direction:"column",gap:4},{default:n(()=>[u.dep?b("",!0):(t(),o(e(W),{key:0,tone:"warning",title:"Needs this deployment's variables",description:"Open Config to set them."})),u.dep&&!m.value?(t(),o(e(Y),{key:1},{header:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...l[12]||(l[12]=[w("Sleep",-1)])]),_:1})]),default:n(()=>[a(e(O),{direction:"column",gap:3},{default:n(()=>[a(e(L),{tone:"muted"},{default:n(()=>[w("Takes the "+q(u.dep.orchestrator==="swarm"?"swarm stack":"compose project")+" down and keeps its volumes. A request to its hostnames wakes it.",1)]),_:1}),a(e(O),{direction:"row",gap:3,wrap:"",align:"center"},{default:n(()=>[a(e(B),{label:"Sleep now",icon:"moon",loading:e(p).pending.value==="sleep",disabled:!!e(p).pending.value||!!$.value,onClick:l[0]||(l[0]=i=>e(p).act("sleep"))},null,8,["loading","disabled"]),$.value?(t(),o(e(L),{key:0,tone:"muted",size:"sm"},{default:n(()=>[w(q($.value),1)]),_:1})):b("",!0)]),_:1})]),_:1})]),_:1})):b("",!0),u.dep?(t(),o(e(Y),{key:2},{header:n(()=>[a(e(O),{direction:"row",gap:3,wrap:"",align:"center",justify:"between"},{default:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...l[13]||(l[13]=[w("Share a read-only link",-1)])]),_:1}),a(wt,{method:"POST",path:e(Ke)(u.id),body:{views:E.value,ttl:S.value}},null,8,["path","body"])]),_:1})]),default:n(()=>[a(e(O),{direction:"column",gap:3},{default:n(()=>[a(e(L),{tone:"muted"},{default:n(()=>[...l[14]||(l[14]=[w("Read-only, this deployment only. No per-link revoke: rotating PSTACK_TOKEN ends every link.",-1)])]),_:1}),a(e(O),{direction:"row",gap:4,wrap:"",align:"end"},{default:n(()=>[a(e(ue),{modelValue:g.value,"onUpdate:modelValue":l[1]||(l[1]=i=>g.value=i),label:"Details and containers"},null,8,["modelValue"]),a(e(ue),{modelValue:U.value,"onUpdate:modelValue":l[2]||(l[2]=i=>U.value=i),label:"Logs"},null,8,["modelValue"]),a(e(ee),{modelValue:S.value,"onUpdate:modelValue":l[3]||(l[3]=i=>S.value=i),label:"Expires in",options:e(Ge)},null,8,["modelValue","options"]),a(e(B),{label:"Create link",loading:D.value,disabled:D.value||!E.value.length,onClick:r},null,8,["loading","disabled"])]),_:1}),E.value.length?b("",!0):(t(),o(e(L),{key:0,tone:"muted",size:"sm"},{default:n(()=>[...l[15]||(l[15]=[w("Pick at least one view.",-1)])]),_:1})),k.value?(t(),o(e(W),{key:1,tone:"danger",title:k.value},null,8,["title"])):b("",!0),h.value?(t(),o(e(W),{key:2,tone:"success",title:"Shown once. Copy it now.",description:`Opens ${h.value.views.join(" and ")} until ${new Date(h.value.expiresAt).toLocaleString()}.`,dismissible:"",onDismiss:l[4]||(l[4]=i=>h.value=null)},{default:n(()=>[a(e(De),{label:"Share link",value:h.value.url,secret:""},null,8,["value"]),a(e(B),{variant:"ghost",label:"Open",icon:"launch",href:h.value.url,target:"_blank"},null,8,["href"])]),_:1},8,["description"])):b("",!0)]),_:1})]),_:1})):b("",!0),u.dep?(t(),o(e(Y),{key:3},{header:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...l[16]||(l[16]=[w("Tear down",-1)])]),_:1})]),default:n(()=>[a(e(O),{direction:"column",gap:3},{default:n(()=>[a(e(L),{tone:"muted"},{default:n(()=>[...l[17]||(l[17]=[w("Stops and removes this deployment's containers, networks and volumes.",-1)])]),_:1}),m.value?(t(),o(e(W),{key:0,tone:"warning",title:"Shared stack",description:"This deletes the volumes every preview on this host depends on. Nothing recreates them."},{default:n(()=>[a(e(Ie),{modelValue:R.value,"onUpdate:modelValue":l[5]||(l[5]=i=>R.value=i),label:`Type ${v.value} to confirm`,placeholder:v.value,autocomplete:"off",error:R.value&&!F.value?"Does not match.":void 0},null,8,["modelValue","label","placeholder","error"])]),_:1})):b("",!0),a(e(O),{direction:"row",gap:3,wrap:"",align:"center"},{default:n(()=>[a(e(B),{variant:"danger",label:m.value?"Tear down (force)":"Tear down",loading:e(p).pending.value==="down",disabled:!!e(p).pending.value||!!x.value,onClick:l[6]||(l[6]=i=>V("down"))},null,8,["label","loading","disabled"]),a(e(B),{variant:"danger",label:"Tear down and forget",loading:e(p).pending.value==="down-forget",disabled:!!e(p).pending.value||!!x.value||!c.value,onClick:l[7]||(l[7]=i=>V("down-forget"))},null,8,["loading","disabled"]),a(e(ue),{modelValue:c.value,"onUpdate:modelValue":l[8]||(l[8]=i=>c.value=i),label:"Check for leftovers afterwards"},null,8,["modelValue"])]),_:1}),x.value?(t(),o(e(L),{key:1,tone:"muted",size:"sm"},{default:n(()=>[w(q(x.value),1)]),_:1})):b("",!0),c.value?b("",!0):(t(),o(e(L),{key:2,tone:"muted",size:"sm"},{default:n(()=>[...l[18]||(l[18]=[w("Nothing will check that the teardown finished. Forgetting needs the check.",-1)])]),_:1})),e(p).busy.value?(t(),o(e(L),{key:3,tone:"muted",size:"sm"},{default:n(()=>[w("A job is running on "+q(v.value)+". Tearing down cancels it first.",1)]),_:1})):b("",!0),a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[...l[19]||(l[19]=[w("Tear down and forget keeps the record if anything is left behind.",-1)])]),_:1}),a(e(O),{direction:"row",gap:3,wrap:"",align:"center"},{default:n(()=>[a(e(B),{variant:"danger",label:"Stop everything on this stack",loading:N.value,disabled:N.value,onClick:l[9]||(l[9]=i=>V("stop"))},null,8,["loading","disabled"]),a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[...l[20]||(l[20]=[w("Destroys nothing. Whatever already ran stays done.",-1)])]),_:1})]),_:1}),K.value?(t(),o(e(W),{key:4,tone:"warning",title:"Stopped mid-run",description:"What it created before stopping is still there. Run Verify.",compact:""})):b("",!0),e(p).error.value?(t(),o(e(W),{key:5,tone:"danger",title:e(p).error.value},null,8,["title"])):b("",!0),e(p).conflict.value?(t(),o(je,{key:6,conflict:e(p).conflict.value,"job-id":e(p).conflictJobId.value},null,8,["conflict","job-id"])):b("",!0)]),_:1})]),_:1})):b("",!0),u.dep?(t(),o(e(Y),{key:4},{header:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...l[21]||(l[21]=[w("Forget this deployment",-1)])]),_:1})]),default:n(()=>[a(e(O),{direction:"column",gap:3},{default:n(()=>[a(e(L),{tone:"muted"},{default:n(()=>[...l[22]||(l[22]=[w("Removes the record only. It never tears anything down. Refused while any container exists, or while Docker cannot confirm.",-1)])]),_:1}),re("div",null,[a(e(B),{variant:"danger",label:"Forget",loading:e(p).pending.value==="forget",disabled:!!e(p).pending.value,onClick:l[10]||(l[10]=i=>V("forget"))},null,8,["loading","disabled"])])]),_:1})]),_:1})):b("",!0),a(e(Re),{open:I.open,"onUpdate:open":l[11]||(l[11]=i=>I.open=i),danger:"",title:`${y[I.kind].title}${I.kind==="stop"?"?":` ${u.id}?`}`,description:y[I.kind].text,"confirm-label":y[I.kind].confirm,onConfirm:d},null,8,["open","title","description","confirm-label"])]),_:1}))}}),$t=Z({__name:"DeploymentLogs",props:{id:{},dep:{},runtime:{}},setup(u){const f=u,p=Ne(),m=ne(),v=A(""),$=A("200"),g=A(""),U=A(!1),S=A(""),h=C(()=>f.runtime?Ve(f.runtime):[]),k=C(()=>h.value.find(y=>y.name===v.value)??null),D=C(()=>{var y;return((y=k.value)==null?void 0:y.service)??""}),E=C(()=>Number($.value)),r=_e({id:()=>f.id,service:D,timestamps:U,tail:E,since:g}),c=C(()=>[{value:"",label:"All services"},...h.value.map(y=>({value:y.name,label:y.service&&y.service!==y.name?`${y.service} (${y.name})`:y.name}))]),R=["50","200","500","1000","2000"].map(y=>({value:y,label:`${y} lines`})),F=[{value:"",label:"Anything kept"},{value:"5m",label:"Last 5 minutes"},{value:"30m",label:"Last 30 minutes"},{value:"1h",label:"Last hour"},{value:"24h",label:"Last day"}],x=C(()=>{var y;return!!((y=f.dep)!=null&&y.compose)}),K=C(()=>{var y;return((y=f.dep)==null?void 0:y.orchestrator)==="swarm"});function N(y){v.value=y,m.replace({query:{...p.query,container:y||void 0}}),!r.following.value&&x.value&&r.fetchOnce()}Q([h,()=>p.query.container],([y,V])=>{const d=typeof V=="string"?V:"";!d||v.value===d||!y.some(s=>s.name===d)||(v.value=d,x.value&&r.fetchOnce())},{immediate:!0}),Q(()=>f.id,()=>{v.value="",S.value="",r.reset()});const T=C(()=>{var s;const y=((s=k.value)==null?void 0:s.name)??"",V=new Set(h.value.map(l=>l.name)),d=[];return r.lines.value.forEach((l,i)=>{const j=nt(l);y&&j.service&&j.service!==y&&V.has(j.service)||d.push({id:String(i),message:j.service&&!y?`${j.service} ${j.message}`:j.message,level:lt(j.message),...j.time?{timestamp:new Date(j.time).toTimeString().slice(0,8)}:{}})}),d});function I(){var s;const y=et(T.value.map(l=>l.message),S.value).join(`
3
+ `),V=URL.createObjectURL(new Blob([y],{type:"text/plain"})),d=document.createElement("a");d.href=V,d.download=tt(f.id,((s=k.value)==null?void 0:s.service)??""),d.click(),URL.revokeObjectURL(V)}return(y,V)=>u.dep?x.value?(t(),o(e(O),{key:2,direction:"column",gap:3},{default:n(()=>[a(e(O),{direction:"row",gap:3,wrap:"",align:"end"},{default:n(()=>[a(e(ee),{"model-value":v.value,label:"Container",options:c.value,onChange:N},null,8,["model-value","options"]),a(e(ee),{modelValue:$.value,"onUpdate:modelValue":V[0]||(V[0]=d=>$.value=d),label:"Lines",options:e(R)},null,8,["modelValue","options"]),a(e(ee),{modelValue:g.value,"onUpdate:modelValue":V[1]||(V[1]=d=>g.value=d),label:"Since",options:F},null,8,["modelValue"]),a(e(qe),{modelValue:U.value,"onUpdate:modelValue":V[2]||(V[2]=d=>U.value=d),label:"Timestamps"},null,8,["modelValue"]),a(e(B),{variant:e(r).following.value?"danger":"secondary",label:e(r).following.value?"Stop following":"Follow",onClick:e(r).toggle},null,8,["variant","label","onClick"]),a(e(B),{label:e(r).touched.value?"Refresh":"Fetch",icon:"arrow",loading:e(r).loading.value,disabled:e(r).following.value,onClick:e(r).fetchOnce},null,8,["label","loading","disabled","onClick"]),a(e(B),{variant:"ghost",icon:"down",label:"Download",disabled:!T.value.length,onClick:I},null,8,["disabled"])]),_:1}),e(r).error.value?(t(),o(e(W),{key:0,tone:"danger",title:e(r).error.value},null,8,["title"])):e(r).touched.value&&!e(r).following.value&&!e(r).lastOk.value?(t(),o(e(W),{key:1,tone:"warning",title:`${K.value?"docker service logs":"Compose"} exited non-zero`,description:u.dep.asleep?"Asleep. No containers to read.":"Usually nothing is brought up yet. What it printed is below.",compact:""},null,8,["title","description"])):b("",!0),e(r).note.value?(t(),o(e(W),{key:2,tone:"info",title:e(r).note.value,compact:""},null,8,["title"])):b("",!0),e(r).touched.value?(t(),o(e(Ee),{key:3,entries:T.value,follow:e(r).following.value,"max-lines":e(he),label:"Deployment logs",wrap:"",onSearchChange:V[3]||(V[3]=d=>S.value=d)},null,8,["entries","follow","max-lines"])):(t(),o(e(L),{key:4,tone:"muted"},{default:n(()=>[...V[4]||(V[4]=[w("Fetch the last lines, or follow live.",-1)])]),_:1})),e(r).following.value?(t(),o(e(L),{key:5,tone:"muted",size:"sm"},{default:n(()=>[w("Following "+q(k.value?k.value.name:"the whole stack")+". Last "+q(e(he).toLocaleString())+" lines kept.",1)]),_:1})):e(r).touched.value&&e(r).lastMeta.value?(t(),o(e(L),{key:6,tone:"muted",size:"sm"},{default:n(()=>[w(q(e(r).lastMeta.value)+". Secrets redacted on the host.",1)]),_:1})):b("",!0)]),_:1})):(t(),o(e(oe),{key:1,title:"No compose section",description:"Nothing to read logs from.",icon:"info"})):(t(),o(e(oe),{key:0,title:"Unavailable",description:"The spec has not resolved.",icon:"info"}))}}),St=Z({__name:"DeploymentOverview",props:{id:{},dep:{},runtime:{},error:{},loading:{type:Boolean}},setup(u){const f=u,p=ne(),m=r=>r?new Date(r).toLocaleString():"—",v=C(()=>{var F,x,K;const r=f.dep;if(!r)return[];const c=r.compose,R=[{key:"stack",label:"Stack",value:r.stack||"—"},{key:"kind",label:"Kind",value:se(r.kind)}];if(r.specName&&R.push({key:"spec",label:"Spec",value:r.specName}),R.push({key:"file",label:"Compose file",value:c?c.file:"none"}),c&&(R.push({key:"profiles",label:"Profiles",value:c.profiles.join(", ")||"none"}),(F=c.subdomains)!=null&&F.length&&R.push({key:"sub",label:"Subdomains",value:c.subdomains.map(N=>`*.${N.host} → ${N.profile}${N.depth==="any"?" (any depth, HTTP only)":""}`).join("; ")}),R.push({key:"orch",label:"Orchestrator",value:r.orchestrator??"compose"})),r.sleep){const N=[r.sleep.idle&&`${r.sleep.idle} idle`,r.sleep.after&&`${r.sleep.after} after deploy`].filter(Boolean);R.push({key:"sleep",label:"Sleep policy",value:N.join(" · ")||"none"})}return c&&R.push({key:"overlays",label:"Overlays",value:c.overlays.join(", ")||"none"}),R.push({key:"axes",label:"Axes",value:((x=r.axes)==null?void 0:x.length)??0},{key:"requires",label:"Requires",value:((K=r.requires)==null?void 0:K.length)??0},{key:"created",label:"Created",value:m(r.createdAt)},{key:"updated",label:"Updated",value:m(r.updatedAt)}),R}),$=C(()=>{var R;const r=(R=f.dep)==null?void 0:R.asleep;if(!r)return"";const c=[...r.hosts,...r.rules.map(F=>`/${F}/`)];return c.length?`Wakes on a request to ${c.join(", ")}.`:"No hostnames. Only Wake brings it back."}),g=A(null),U=A(""),S=A(!1);async function h(){S.value=!0,U.value="";const r=await X.readiness(f.id);if(S.value=!1,!r.ok){U.value=G(r.status,r.body.error,"Readiness");return}g.value=r.body}const k=[{key:"name",label:"Container",truncate:!0},{key:"state",label:"State"},{key:"health",label:"Health",hideBelow:480},{key:"restarts",label:"Restarts",align:"end",hideBelow:560},{key:"reason",label:"Reason",hideBelow:640}],D=C(()=>{var r;return(((r=g.value)==null?void 0:r.containers)??[]).map(c=>({id:c.name,name:c.name,state:c.failed?"Failed":c.ready?"Ready":"Waiting",health:c.hasHealthcheck?c.health??"—":"No healthcheck",restarts:c.restartCount,reason:c.reason??""}))}),E=C(()=>{var r,c,R;return((r=g.value)==null?void 0:r.state)==="ready"?"success":((c=g.value)==null?void 0:c.state)==="failed"||((R=g.value)==null?void 0:R.state)==="timedout"?"danger":"info"});return(r,c)=>(t(),o(e(O),{direction:"column",gap:4},{default:n(()=>{var R,F;return[u.error?(t(),o(e(W),{key:0,tone:"danger",title:"Could not resolve this deployment",description:u.error},{default:n(()=>[a(e(B),{variant:"secondary",label:"Open Config",onClick:c[0]||(c[0]=x=>e(p).push(`/deployments/${encodeURIComponent(u.id)}/config`))})]),_:1},8,["description"])):b("",!0),(R=u.dep)!=null&&R.asleep?(t(),o(e(W),{key:1,tone:"info",title:`Asleep since ${m(u.dep.asleep.since)}`,description:`${u.dep.asleep.reason}. ${$.value}`},null,8,["title","description"])):b("",!0),(F=u.runtime)!=null&&F.findings.length?(t(),o(e(W),{key:2,tone:u.runtime.findings.some(x=>x.level==="error")?"danger":"warning",title:`${u.runtime.findings.length} finding${u.runtime.findings.length===1?"":"s"}`},{default:n(()=>[a(e(B),{variant:"ghost",label:"See containers and routes",onClick:c[1]||(c[1]=x=>e(p).push(`/deployments/${encodeURIComponent(u.id)}/runtime`))})]),_:1},8,["tone","title"])):b("",!0),a(e(Y),null,{header:n(()=>[a(e(O),{direction:"row",gap:3,wrap:"",align:"center",justify:"between"},{default:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...c[4]||(c[4]=[w("Resolved spec",-1)])]),_:1}),u.dep&&e(pe)("developer",e(fe))?(t(),o(e(O),{key:0,direction:"row",gap:2,wrap:""},{default:n(()=>[a(e(B),{variant:"ghost",label:"Duplicate",onClick:c[2]||(c[2]=x=>e(p).push({path:"/submit",query:{from:u.id}}))}),a(e(B),{variant:"ghost",label:"Edit spec and compose","trailing-icon":"right",onClick:c[3]||(c[3]=x=>e(p).push(`/submit/${encodeURIComponent(u.id)}`))})]),_:1})):b("",!0)]),_:1})]),default:n(()=>[u.loading&&!u.dep?(t(),o(e(le),{key:0,variant:"rectangle",height:"10rem",label:"Loading spec"})):u.dep?(t(),o(e($e),{key:2,items:v.value,columns:"auto","min-column-width":"14rem"},null,8,["items"])):(t(),o(e(L),{key:1,tone:"muted"},{default:n(()=>[...c[5]||(c[5]=[w("Spec not resolved.",-1)])]),_:1}))]),_:1}),a(e(Y),null,{header:n(()=>[a(e(O),{direction:"row",gap:3,wrap:"",align:"center",justify:"between"},{default:n(()=>{var x;return[a(e(O),{direction:"row",gap:2,align:"center"},{default:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...c[6]||(c[6]=[w("Readiness",-1)])]),_:1}),g.value?(t(),o(e(J),{key:0,label:e(se)(g.value.state),tone:E.value,dot:""},null,8,["label","tone"])):b("",!0)]),_:1}),a(e(B),{variant:"secondary",icon:"arrow",label:"Check",loading:S.value,disabled:!((x=u.dep)!=null&&x.stack),onClick:h},null,8,["loading","disabled"])]}),_:1})]),default:n(()=>[U.value?(t(),o(e(W),{key:0,tone:"danger",title:U.value,compact:""},null,8,["title"])):g.value&&!g.value.reachable?(t(),o(e(W),{key:1,tone:"warning",title:"Docker did not answer",description:"Container fields are the last known.",compact:""})):b("",!0),g.value?(t(),o(e(te),{key:2,label:"Readiness",rows:D.value,columns:k,"empty-text":"No containers yet."},null,8,["rows"])):U.value?b("",!0):(t(),o(e(L),{key:3,tone:"muted"},{default:n(()=>{var x;return[w(q((x=u.dep)!=null&&x.stack?"Not checked.":"Needs variables."),1)]}),_:1}))]),_:1})]}),_:1}))}}),Rt=Z({__name:"RequiresTab",props:{id:{},dep:{},runtime:{}},setup(u){const f=u;Q(()=>f.id,ge,{immediate:!0});const p=[{key:"name",label:"Requirement"},{key:"hint",label:"Hint on failure"}],m=C(()=>{var v;return(((v=P.data)==null?void 0:v.requires)??[]).map($=>({id:$.name,name:$.name,hint:$.hint||"No hint"}))});return(v,$)=>(t(),o(e(Y),{title:"Requires",description:"Checked before anything is created."},{footer:n(()=>[a(e(B),{variant:"secondary",icon:"arrow",label:"Re-resolve",loading:e(P).loading,onClick:e(Ae)},null,8,["loading","onClick"])]),default:n(()=>[e(P).loading&&!e(P).data&&!e(P).error?(t(),o(e(le),{key:0,variant:"text",lines:3,label:"Loading requirements"})):e(P).error?(t(),o(e(W),{key:1,tone:"danger",title:"Spec did not resolve",description:e(P).error},null,8,["description"])):(t(),o(e(O),{key:2,direction:"column",gap:3},{default:n(()=>[a(e(te),{rows:m.value,columns:p,label:"Requirements","empty-text":"None declared."},null,8,["rows"])]),_:1}))]),_:1}))}}),Tt=["href"],Nt=Z({__name:"RuntimeTab",props:{id:{},dep:{},runtime:{},error:{},loading:{type:Boolean}},emits:["refresh"],setup(u,{emit:f}){const p=u,m=f,v=ne(),$=(d,s)=>v.push({path:`/deployments/${encodeURIComponent(p.id)}/${d}`,query:{container:s}}),g=C(()=>p.runtime?Ve(p.runtime):[]),U=C(()=>g.value.filter(d=>d.state==="running").length),S=C(()=>g.value.some(d=>d.node)),h=C(()=>{var d;return it(((d=p.runtime)==null?void 0:d.findings)??[])}),k=C(()=>{var d;return((d=h.value[0])==null?void 0:d.level)??"info"}),D=A(!1),E=[{key:"url",label:"URL",minWidth:"12rem"},{key:"target",label:"Forwards to",hideBelow:520},{key:"router",label:"Router",truncate:!0,hideBelow:700},{key:"tls",label:"TLS",hideBelow:420}],r=C(()=>{var d;return(((d=p.runtime)==null?void 0:d.routes)??[]).map(s=>({id:s.router,hosts:s.hosts,rule:s.rule,target:rt(s),container:s.container,router:s.router,priority:s.priority,tls:s.tls?s.certresolver||"inherited":""}))}),c=C(()=>[{key:"service",label:"Service",minWidth:"10rem"},...S.value?[{key:"node",label:"Node",hideBelow:760}]:[],{key:"state",label:"State"},{key:"ports",label:"Ports",hideBelow:640},{key:"networks",label:"Networks",hideBelow:900},{key:"image",label:"Image",truncate:!0,hideBelow:1e3}]),R=C(()=>pt(g.value,d=>d.name,d=>d.id)),F=C(()=>[...R.value].map(([d,s])=>({id:d,c:s,st:st(s)}))),x=d=>R.value.get(d);function K(d){const s=d.c,l=!!N.value,i=[];return s.id.startsWith("service:")?[{id:"logs",label:"Logs"}]:(!s.job&&!s.remote&&(i.push(s.state!=="running"?{id:"start",label:"Start",disabled:l}:{id:"stop",label:"Stop",disabled:l,danger:!0}),i.push({id:"restart",label:"Restart",disabled:l})),i.push({id:"logs",label:"Logs"}),s.state==="running"&&!s.remote&&!s.job&&i.push({id:"shell",label:"Shell"}),s.state==="running"&&Ce(p.runtime,s)&&i.push({id:"open",label:"Open",icon:"launch"}),i)}const N=A(""),T=Te({open:!1,c:null,action:"stop"}),I={start:"Start",stop:"Stop",restart:"Restart"};function y(d){const s=x(d.id);if(s)if(d.action==="logs")$("logs",s.name);else if(d.action==="shell")$("terminal",s.name);else if(d.action==="open"){const l=Ce(p.runtime,s);l&&window.open(l,"_blank","noopener")}else T.c=s,T.action=d.action,T.open=!0}async function V(){const d=T.c;if(!d)return;N.value=`${T.action}:${d.name}`;const s=await X.container(p.id,d.name,T.action);if(N.value="",T.open=!1,!s.ok){_(`${I[T.action]} refused`,"danger",G(s.status,s.body.error,d.name));return}_(s.body.note??`${I[T.action]} sent`,"success",d.name),m("refresh")}return(d,s)=>(t(),o(e(O),{direction:"column",gap:4},{default:n(()=>{var l;return[u.error?(t(),o(e(W),{key:0,tone:"danger",title:"Could not inspect this deployment",description:u.error},null,8,["description"])):b("",!0),u.loading&&!u.runtime?(t(),o(e(le),{key:1,variant:"rectangle",height:"12rem",label:"Loading runtime"})):u.runtime?(t(),z(M,{key:2},[u.runtime.reachable?(t(),z(M,{key:1},[a(e(O),{direction:"row",gap:3,wrap:"",align:"center"},{default:n(()=>[h.value.length?(t(),o(e(B),{key:0,variant:"secondary",icon:"info",label:`${h.value.length} ${e(we)(k.value).toLowerCase()}`,onClick:s[0]||(s[0]=i=>D.value=!0)},null,8,["label"])):g.value.length?(t(),o(e(W),{key:1,tone:"success",title:"Nothing looks wrong",compact:""})):b("",!0)]),_:1}),a(e(Y),null,{header:n(()=>[a(e(O),{direction:"row",gap:3,wrap:"",align:"center",justify:"between"},{default:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...s[5]||(s[5]=[w("Routing",-1)])]),_:1}),a(e(O),{direction:"row",gap:2,align:"center",wrap:""},{default:n(()=>[a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[w("TLS: "+q(u.runtime.challenge),1)]),_:1}),a(e(B),{variant:"ghost",label:"Change on Control",onClick:s[1]||(s[1]=i=>e(v).push("/control"))})]),_:1})]),_:1})]),default:n(()=>[r.value.length?(t(),o(e(te),{key:1,label:"Routes",rows:r.value,columns:E},{cell:n(({row:i,column:j})=>[j.key==="url"?(t(),z(M,{key:0},[(t(!0),z(M,null,ae(i.hosts,H=>(t(),z("div",{key:H},[H.startsWith("(pattern)")?(t(),o(e(L),{key:1,as:"code",tone:"muted"},{default:n(()=>[w(q(H),1)]),_:2},1024)):(t(),z("a",{key:0,href:`https://${H}`,target:"_blank",rel:"noopener noreferrer"},q(H),9,Tt))]))),128)),i.hosts.length?b("",!0):(t(),o(e(L),{key:0,tone:"muted"},{default:n(()=>[...s[6]||(s[6]=[w("No host in the rule",-1)])]),_:1}))],64)):j.key==="target"?(t(),z(M,{key:1},[a(e(J),{label:i.target.text,tone:i.target.tone,title:i.target.hint},null,8,["label","tone","title"]),re("div",null,[a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[w(q(i.container),1)]),_:2},1024)])],64)):j.key==="router"?(t(),z(M,{key:2},[w(q(i.router),1),i.priority?(t(),z(M,{key:0},[w(" · priority "+q(i.priority),1)],64)):b("",!0)],64)):j.key==="tls"?(t(),z(M,{key:3},[i.tls?(t(),o(e(J),{key:0,label:String(i.tls),tone:"success"},null,8,["label"])):(t(),o(e(J),{key:1,label:"Off"}))],64)):b("",!0)]),_:1},8,["rows"])):(t(),o(e(oe),{key:0,title:"No routes",description:"Traefik labels come from your compose file.",icon:"globe"}))]),_:1}),a(e(Y),null,{header:n(()=>[a(e(O),{direction:"row",gap:3,wrap:"",align:"center",justify:"between"},{default:n(()=>[a(e(L),{weight:"medium"},{default:n(()=>[...s[7]||(s[7]=[w("Containers",-1)])]),_:1}),a(e(O),{direction:"row",gap:2,align:"center"},{default:n(()=>[a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[w(q(U.value)+" of "+q(g.value.length)+" running",1)]),_:1}),a(e(B),{variant:"ghost",icon:"arrow",label:"Refresh",loading:u.loading,onClick:s[2]||(s[2]=i=>m("refresh"))},null,8,["loading"])]),_:1})]),_:1})]),default:n(()=>[g.value.length?(t(),o(e(te),{key:1,label:"Containers",rows:F.value,columns:c.value,"get-row-actions":K,"action-display":"label",onRowAction:y},{cell:n(({row:i,column:j})=>[j.key==="service"?(t(),z(M,{key:0},[re("div",null,q(i.c.service??i.c.name),1),i.c.id.startsWith("service:")?b("",!0):(t(),o(e(L),{key:0,tone:"muted",size:"sm",title:i.c.name},{default:n(()=>[w(q(e(at)(i.c.name)),1)]),_:2},1032,["title"]))],64)):j.key==="node"?(t(),z(M,{key:1},[w(q(i.c.node??"—")+" ",1),i.c.remote?(t(),o(e(J),{key:0,label:"Remote",title:"On another node. Logs reach it; a shell and stop/start do not."})):b("",!0)],64)):j.key==="state"?(t(),z(M,{key:2},[a(e(J),{dot:"",label:i.st.label,tone:i.st.tone},null,8,["label","tone"]),i.c.job?(t(),o(e(J),{key:0,label:"One-shot",title:"No container to start, stop or shell into."})):b("",!0),i.c.restartCount>0?(t(),o(e(J),{key:1,label:`${i.c.restartCount}x restarted`,tone:"warning"},null,8,["label"])):b("",!0)],64)):j.key==="ports"?(t(),z(M,{key:3},[(t(!0),z(M,null,ae(i.c.ports,H=>(t(),z("div",{key:`${H.containerPort}/${H.protocol}`},[w(q(H.containerPort),1),H.hostPort?(t(),o(e(L),{key:0,tone:"muted"},{default:n(()=>[w(" ← host "+q(H.hostPort),1)]),_:2},1024)):b("",!0)]))),128)),i.c.ports.length?b("",!0):(t(),o(e(L),{key:0,tone:"muted"},{default:n(()=>[...s[8]||(s[8]=[w("None",-1)])]),_:1}))],64)):j.key==="networks"?(t(),z(M,{key:4},[(t(!0),z(M,null,ae(i.c.networks,H=>(t(),z("div",{key:H},q(H),1))),128)),i.c.ingressIp?(t(),o(e(L),{key:0,as:"code",tone:"muted",size:"sm"},{default:n(()=>[w(q(i.c.ingressIp),1)]),_:2},1024)):b("",!0)],64)):j.key==="image"?(t(),z(M,{key:5},[w(q(i.c.image),1)],64)):b("",!0)]),_:1},8,["rows","columns"])):(t(),o(e(oe),{key:0,title:"No containers",description:"Nothing is running for this stack.",icon:"server"}))]),_:1})],64)):(t(),o(e(W),{key:0,tone:"warning",title:"Docker did not answer",description:"That is not the same as nothing running."}))],64)):b("",!0),a(e(Se),{open:D.value,title:"What pstack noticed",onClose:s[3]||(s[3]=i=>D.value=!1)},{default:n(()=>[a(e(O),{direction:"column",gap:3},{default:n(()=>[(t(!0),z(M,null,ae(h.value,(i,j)=>(t(),o(e(W),{key:j,tone:e(ot)(i.level),title:e(we)(i.level),description:i.message},null,8,["tone","title","description"]))),128))]),_:1})]),_:1},8,["open"]),a(e(Re),{open:T.open,"onUpdate:open":s[4]||(s[4]=i=>T.open=i),danger:T.action!=="start",busy:!!N.value,title:`${I[T.action]} ${((l=T.c)==null?void 0:l.name)??""}?`,description:T.action==="stop"?"This container only. It stays stopped until something starts it.":"This container only.","confirm-label":I[T.action],onConfirm:V},null,8,["open","danger","busy","title","description","confirm-label"])]}),_:1}))}}),xt=Z({__name:"TerminalTab",props:{id:{},dep:{},runtime:{},error:{}},setup(u){const f=u,p=Ne(),m=["sh","bash","ash","zsh","fish"].map(N=>({value:N,label:N})),v=A(""),$=A("sh"),g=A("idle"),U=A(""),S=A(null),h=be(null),k=be(null);let D=null,E=0;const r=C(()=>{var N;return(((N=f.runtime)==null?void 0:N.containers)??[]).filter(T=>T.state==="running"&&!T.remote&&!T.job)}),c=C(()=>r.value.map(N=>({value:N.name,label:N.service?`${N.service} (${N.name})`:N.name}))),R=C(()=>g.value==="open"||g.value==="connecting");Q(r,N=>{var I,y;if(v.value&&N.some(V=>V.name===v.value))return;const T=typeof p.query.container=="string"?p.query.container:"";v.value=((I=N.find(V=>V.name===T))==null?void 0:I.name)??((y=N[0])==null?void 0:y.name)??""},{immediate:!0});async function F(){var s;if(R.value||!v.value)return;U.value="",g.value="connecting";const N=E,[{Terminal:T},{FitAddon:I}]=await Promise.all([ye(()=>import("./xterm-D6Mng-DB.js").then(l=>l.x),__vite__mapDeps([0,1])),ye(()=>import("./addon-fit-CevVMrUA.js").then(l=>l.a),__vite__mapDeps([2,1]))]);if(N!==E)return;(s=h.value)==null||s.dispose();const y=new T({convertEol:!0,fontSize:13,fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",cursorBlink:!0,theme:{background:"#0b0e14"}}),V=new I;y.loadAddon(V),S.value&&(S.value.replaceChildren(),y.open(S.value),V.fit()),h.value=y,D==null||D.disconnect(),D=new ResizeObserver(()=>{try{V.fit()}catch{}}),S.value&&D.observe(S.value);const d=new WebSocket(He(f.id,v.value,$.value));d.binaryType="arraybuffer",k.value=d,d.onopen=()=>{g.value="open",y.focus()},d.onmessage=l=>y.write(typeof l.data=="string"?l.data:new Uint8Array(l.data)),d.onclose=l=>{g.value="closed",U.value=l.reason||(l.code===1006?"connection dropped":`code ${l.code}`)},d.onerror=()=>{g.value==="connecting"&&(U.value="could not connect")},y.onData(l=>{d.readyState===WebSocket.OPEN&&d.send(l)})}function x(){if(!k.value){E++,g.value="idle";return}k.value.close(1e3,"closed by the operator")}function K(){var N,T;E++,k.value&&(k.value.onclose=k.value.onmessage=k.value.onerror=k.value.onopen=null),D==null||D.disconnect(),D=null,(N=k.value)==null||N.close(),k.value=null,(T=h.value)==null||T.dispose(),h.value=null}return Q([v,$],()=>{R.value&&x()}),Q(()=>f.id,()=>{K(),g.value="idle",U.value=""}),xe(K),(N,T)=>(t(),o(e(O),{direction:"column",gap:3},{default:n(()=>[a(e(W),{tone:"warning",title:"No TTY",description:"No prompt, no Ctrl-C, no full-screen programs.",compact:""}),a(e(O),{direction:"row",gap:3,wrap:"",align:"end"},{default:n(()=>[a(e(ee),{modelValue:v.value,"onUpdate:modelValue":T[0]||(T[0]=I=>v.value=I),label:"Container",options:c.value,disabled:R.value||!c.value.length,placeholder:c.value.length?void 0:u.runtime?"No container":"Loading"},null,8,["modelValue","options","disabled","placeholder"]),a(e(ee),{modelValue:$.value,"onUpdate:modelValue":T[1]||(T[1]=I=>$.value=I),label:"Shell",options:e(m),disabled:R.value},null,8,["modelValue","options","disabled"]),g.value!=="open"?(t(),o(e(B),{key:0,label:"Open shell",loading:g.value==="connecting",disabled:!v.value,onClick:F},null,8,["loading","disabled"])):(t(),o(e(B),{key:1,variant:"secondary",label:"Close shell",onClick:x})),g.value==="open"?(t(),o(e(J),{key:2,dot:"",tone:"success",label:"Connected"})):b("",!0)]),_:1}),u.error?(t(),o(e(W),{key:0,tone:"danger",title:"Could not list containers",description:u.error},null,8,["description"])):r.value.length?b("",!0):(t(),o(e(L),{key:1,tone:"muted"},{default:n(()=>[w(q(u.runtime?"No container to open a shell in.":"Loading containers."),1)]),_:1})),g.value==="closed"&&U.value?(t(),o(e(L),{key:2,tone:"muted"},{default:n(()=>[w("Session ended: "+q(U.value)+".",1)]),_:1})):b("",!0),ze(re("div",{ref_key:"host",ref:S,class:"term",role:"group","aria-label":"Terminal"},null,512),[[Be,g.value!=="idle"]]),a(e(L),{tone:"muted",size:"sm"},{default:n(()=>[...T[2]||(T[2]=[w("Every session is recorded: who, which container, when.",-1)])]),_:1})]),_:1}))}}),Lt=Oe(xt,[["__scopeId","data-v-fe2ef41e"]]),Bt=Z({__name:"DeploymentView",props:{id:{},tab:{}},setup(u){const f=u,p=ne(),m=A(null),v=A(null),$=A(!1),g=A(!0),U=A(!1),S=A(""),h=A(""),k=ft(()=>f.id,m);async function D(){const l=f.id,[i,j]=await Promise.all([X.detail(l),X.runtime(l)]);if(l===f.id){if(g.value=!1,i.status===404){$.value=!0,r&&clearInterval(r);return}i.ok?(m.value=i.body,S.value=""):m.value&&(i.status===0||i.status>=500)?S.value=G(i.status,i.body.error,"Deployment"):(m.value=null,S.value=G(i.status,i.body.error,"Deployment")),j.ok?(v.value=j.body,h.value=""):h.value=G(j.status,j.body.error,"Runtime")}}async function E(){U.value=!0,await D(),U.value=!1}let r,c=ce(de(f.id));Q(()=>P.loading,l=>{if(l||P.id!==f.id)return;const i=ce(de(f.id));i!==c&&(c=i,D())}),Q(()=>f.id,()=>{c=ce(de(f.id)),m.value=null,v.value=null,$.value=!1,g.value=!0,S.value="",h.value="",k.reset(),D(),r&&clearInterval(r),r=setInterval(()=>!document.hidden&&void D(),6e3)},{immediate:!0}),xe(()=>r&&clearInterval(r));const R=C({get:()=>f.tab==="containers"?"runtime":f.tab??"overview",set:l=>void p.replace(`/deployments/${encodeURIComponent(f.id)}/${l}`)}),F=[{value:"overview",label:"Overview"},{value:"runtime",label:"Containers and routes"},{value:"config",label:"Config and variables"},{value:"axes",label:"Axes"},{value:"requires",label:"Requires"},{value:"logs",label:"Logs"},{value:"terminal",label:"Terminal"},{value:"jobs",label:"Jobs"},{value:"danger",label:"Danger"}],x=C(()=>pe("developer",fe)?F:F.filter(l=>l.value!=="terminal"&&l.value!=="danger"));Q(S,l=>{l&&!f.tab&&p.replace(`/deployments/${encodeURIComponent(f.id)}/config`)});const K=C(()=>{var l;return m.value?ut({busy:m.value.busy,asleep:m.value.asleep,running:((l=me.deployments.find(i=>i.id===f.id))==null?void 0:l.running)??null}):{label:S.value?"Unresolved":"Loading",tone:"neutral"}}),N=C(()=>{var l;return((l=m.value)==null?void 0:l.kind)==="shared"}),T=C(()=>{var l,i,j,H;return[{key:"stack",label:"Stack",value:((l=m.value)==null?void 0:l.stack)??(S.value?"unresolved":"—")},{key:"kind",label:"Kind",value:m.value?se(m.value.kind):"—"},{key:"orchestrator",label:"Orchestrator",value:((i=m.value)==null?void 0:i.orchestrator)??"none"},{key:"spec",label:"Spec",value:((j=m.value)==null?void 0:j.specName)??"inline"},{key:"updated",label:"Updated",value:ke((H=m.value)==null?void 0:H.updatedAt)}]}),I=C(()=>{var l;return(l=m.value)!=null&&l.asleep?"wake":"up"}),y=C(()=>k.why(I.value)),{pending:V}=k,d=C(()=>me.jobs.filter(l=>l.deployment===f.id)),s=C(()=>d.value.map(l=>({id:l.id,title:Le[l.action]??l.action,description:`${se(l.state)}${l.endedAt?` in ${Je(l.startedAt,l.endedAt)}`:""}`,timestamp:ke(l.startedAt),href:`/jobs/${encodeURIComponent(l.id)}`,tone:Me(l.state)})));return(l,i)=>{var j;return g.value?(t(),o(e(le),{key:0,variant:"rectangle",label:"Loading deployment"})):$.value?(t(),o(e(Fe),{key:1,kind:"not-found",brand:"pstack","home-href":"/deployments",title:`No deployment ${u.id}`,description:"It may have been forgotten."},null,8,["title"])):(t(),o(e(Pe),{key:2,title:u.id,description:((j=m.value)==null?void 0:j.stack)??(S.value?"unresolved":""),breadcrumbs:[{id:"deployments",label:"Deployments"},{id:"self",label:u.id}],status:K.value.label,tone:K.value.tone,fields:T.value,tabs:x.value,"active-tab":R.value,"onUpdate:activeTab":i[2]||(i[2]=H=>R.value=H),onNavigate:i[3]||(i[3]=H=>e(p).push("/deployments"))},{actions:n(()=>[a(e(B),{variant:"ghost",icon:"arrow",label:"Re-resolve",loading:U.value,onClick:E},null,8,["loading"]),a(e(B),{label:I.value==="wake"?"Wake":"Deploy",icon:I.value==="wake"?"sun":"up",loading:e(V)===I.value,disabled:!!e(V)||!!y.value,onClick:i[0]||(i[0]=H=>e(k).act(I.value))},null,8,["label","icon","loading","disabled"]),a(e(B),{variant:"secondary",icon:"check",label:"Verify",loading:e(V)==="verify",disabled:!!e(V)||!!e(k).why("verify"),onClick:i[1]||(i[1]=H=>e(k).act("verify"))},null,8,["loading","disabled"])]),summary:n(()=>[a(e(O),{direction:"column",gap:2},{default:n(()=>[a(e(O),{direction:"row",gap:2,wrap:"",align:"center"},{default:n(()=>{var H;return[((H=m.value)==null?void 0:H.orchestrator)==="swarm"?(t(),o(e(J),{key:0,label:"Swarm"})):b("",!0),N.value?(t(),o(e(L),{key:1,tone:"muted",size:"sm"},{default:n(()=>[...i[4]||(i[4]=[w("Shared with every preview on this host.",-1)])]),_:1})):b("",!0),y.value&&m.value?(t(),o(e(L),{key:2,tone:"muted",size:"sm"},{default:n(()=>[w(q(y.value),1)]),_:1})):b("",!0)]}),_:1}),e(k).error.value?(t(),o(e(W),{key:0,tone:"danger",title:e(k).error.value},null,8,["title"])):b("",!0),e(k).conflict.value?(t(),o(je,{key:1,conflict:e(k).conflict.value,"job-id":e(k).conflictJobId.value},null,8,["conflict","job-id"])):b("",!0)]),_:1})]),overview:n(()=>[a(St,{id:u.id,dep:m.value,runtime:v.value,error:S.value,loading:g.value},null,8,["id","dep","runtime","error","loading"])]),config:n(()=>[a(ht,{id:u.id,dep:m.value,runtime:v.value},null,8,["id","dep","runtime"])]),runtime:n(()=>[a(Nt,{id:u.id,dep:m.value,runtime:v.value,error:h.value,loading:U.value,onRefresh:E},null,8,["id","dep","runtime","error","loading"])]),axes:n(()=>[a(gt,{id:u.id,dep:m.value,runtime:v.value},null,8,["id","dep","runtime"])]),requires:n(()=>[a(Rt,{id:u.id,dep:m.value,runtime:v.value},null,8,["id","dep","runtime"])]),terminal:n(()=>[a(Lt,{id:u.id,dep:m.value,runtime:v.value,error:h.value},null,8,["id","dep","runtime","error"])]),logs:n(()=>[a($t,{id:u.id,dep:m.value,runtime:v.value},null,8,["id","dep","runtime"])]),jobs:n(()=>[s.value.length?(t(),o(e(We),{key:1,items:s.value,label:"Jobs"},null,8,["items"])):(t(),o(e(oe),{key:0,title:"No jobs for this deployment",icon:"clock"}))]),danger:n(()=>[a(Ct,{id:u.id,dep:m.value,actions:e(k)},null,8,["id","dep","actions"])]),_:1},8,["title","description","breadcrumbs","status","tone","fields","tabs","active-tab"]))}}});export{Bt as default};
4
+ //# sourceMappingURL=DeploymentView-D_wV0QNw.js.map