@adonis-agora/media 0.10.3 → 0.11.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 (48) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +46 -6
  3. package/dist/assets/spa/assets/index--0MZJr6W.css +1 -0
  4. package/dist/assets/spa/assets/index-Dvw2uJpF.js +83 -0
  5. package/dist/assets/spa/assets/index-Dvw2uJpF.js.map +1 -0
  6. package/dist/assets/spa/index.html +20 -0
  7. package/dist/configure.d.ts +6 -2
  8. package/dist/configure.d.ts.map +1 -1
  9. package/dist/configure.js +8 -2
  10. package/dist/configure.js.map +1 -1
  11. package/dist/providers/dashboard_provider.d.ts +29 -0
  12. package/dist/providers/dashboard_provider.d.ts.map +1 -0
  13. package/dist/providers/dashboard_provider.js +520 -0
  14. package/dist/providers/dashboard_provider.js.map +1 -0
  15. package/dist/src/dashboard/auth.d.ts +76 -0
  16. package/dist/src/dashboard/auth.d.ts.map +1 -0
  17. package/dist/src/dashboard/auth.js +134 -0
  18. package/dist/src/dashboard/auth.js.map +1 -0
  19. package/dist/src/dashboard/cookie.d.ts +20 -0
  20. package/dist/src/dashboard/cookie.d.ts.map +1 -0
  21. package/dist/src/dashboard/cookie.js +44 -0
  22. package/dist/src/dashboard/cookie.js.map +1 -0
  23. package/dist/src/dashboard/define_config.d.ts +56 -0
  24. package/dist/src/dashboard/define_config.d.ts.map +1 -0
  25. package/dist/src/dashboard/define_config.js +5 -0
  26. package/dist/src/dashboard/define_config.js.map +1 -0
  27. package/dist/src/dashboard/index.d.ts +10 -0
  28. package/dist/src/dashboard/index.d.ts.map +1 -0
  29. package/dist/src/dashboard/index.js +9 -0
  30. package/dist/src/dashboard/index.js.map +1 -0
  31. package/dist/src/dashboard/object_insights.d.ts +42 -0
  32. package/dist/src/dashboard/object_insights.d.ts.map +1 -0
  33. package/dist/src/dashboard/object_insights.js +42 -0
  34. package/dist/src/dashboard/object_insights.js.map +1 -0
  35. package/dist/src/dashboard/service.d.ts +215 -0
  36. package/dist/src/dashboard/service.d.ts.map +1 -0
  37. package/dist/src/dashboard/service.js +470 -0
  38. package/dist/src/dashboard/service.js.map +1 -0
  39. package/dist/src/dashboard/spa.d.ts +29 -0
  40. package/dist/src/dashboard/spa.d.ts.map +1 -0
  41. package/dist/src/dashboard/spa.js +47 -0
  42. package/dist/src/dashboard/spa.js.map +1 -0
  43. package/dist/src/dashboard/types.d.ts +201 -0
  44. package/dist/src/dashboard/types.d.ts.map +1 -0
  45. package/dist/src/dashboard/types.js +10 -0
  46. package/dist/src/dashboard/types.js.map +1 -0
  47. package/dist/stubs/config/media_dashboard.stub +39 -0
  48. package/package.json +20 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @adonis-agora/media
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`ad61387`](https://github.com/DavideCarvalho/adonis-agora-media/commit/ad61387aba714ba85ce6a6cf810b97259db46a93) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - The management console now ships **embedded** — `@adonis-agora/media/dashboard_provider` mounts the same React SPA + JSON API `@adonis-agora/media-dashboard` always has, straight from this package. `node ace configure @adonis-agora/media` registers it automatically (alongside publishing `config/media_dashboard.ts`); no separate `@adonis-agora/media-dashboard` install is required to get the console.
8
+
9
+ New subpath exports:
10
+
11
+ - `@adonis-agora/media/dashboard_provider` — the provider (routes: SPA + assets, JSON API, session auth). Reads the same `media_dashboard` config key `@adonis-agora/media-dashboard`'s provider always did, so an existing `config/media_dashboard.ts` keeps working unchanged if you switch to this provider.
12
+ - `@adonis-agora/media/dashboard` — `defineConfig`/`MediaDashboardConfig` for authoring `config/media_dashboard.ts`, `DashboardService`/`DashboardError`, the built-in session-auth helpers (`resolveConsoleAuth`, `signSessionCookie`, `verifySessionCookie`), `ObjectInsightProvider`/`sanitizeInsight`, and the dashboard's JSON API types.
13
+
14
+ `MediaDashboardConfig` also gains `enabled` (default `true`) — set `false` to register the provider without mounting any route.
15
+
16
+ At build time, `pnpm build` copies `@adonis-agora/media-dashboard`'s built SPA (`dist/spa`) into this package's own `dist/assets/spa`, mirroring `@adonis-agora/durable`'s embedded-dashboard pattern. `@adonis-agora/media-dashboard` remains published, standalone-installable, and its own provider (`@adonis-agora/media-dashboard/media_dashboard_provider`) still works — see that package's own changeset for what changed there. Register only one of the two dashboard providers in a given app.
17
+
18
+ ## 0.10.4
19
+
20
+ ### Patch Changes
21
+
22
+ - [`a06b2df`](https://github.com/DavideCarvalho/adonis-media/commit/a06b2df5194259be83fa08e8af15e7f9b07c48b3) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Widen the `@adonisjs/drive` peer dependency from `^3.0.0` to `^3.0.0 || ^4.0.0`.
23
+
24
+ Verified compatible by running the real test suite against `@adonisjs/drive@4` (the package's dev dependency is bumped accordingly). No source changes were needed — this is a non-breaking relaxation of the accepted peer range, so consumers can adopt Drive v4 without waiting on a major bump here.
25
+
3
26
  ## 0.10.3
4
27
 
5
28
  ### Patch Changes
package/README.md CHANGED
@@ -9,11 +9,11 @@ you reuse your existing `local` / `s3` / `gcs` disks — this package never reim
9
9
 
10
10
  This is the **core library**: `MediaLibrary`, `AttachmentManager`, the `MediaStore` SPI (in-memory +
11
11
  Lucid), the `ImageProcessor` SPI (sharp), the bundled `disks.s3()` driver, proxy/direct/resumable
12
- uploads, configurable delivery, the provider + `defineConfig`, and a testing kit. Pair it with
12
+ uploads, configurable delivery, the provider + `defineConfig`, and a testing kit. The management
13
+ **console ships embedded** — registering `@adonis-agora/media/dashboard_provider` is all a consuming
14
+ app needs (see [Dashboard](#dashboard) below); no separate install. Pair it with
13
15
  [`@adonis-agora/media-react`](https://github.com/DavideCarvalho/adonis-media/tree/master/packages/react)
14
- for a browser upload client, or
15
- [`@adonis-agora/media-dashboard`](https://github.com/DavideCarvalho/adonis-media/tree/master/packages/dashboard)
16
- for a management console.
16
+ for a browser upload client.
17
17
 
18
18
  ## Subpath exports
19
19
 
@@ -23,6 +23,8 @@ The package uses **subpath exports** (the Agora idiom), so heavy backends stay o
23
23
  |---|---|
24
24
  | `@adonis-agora/media` | barrel — `defineConfig`, `stores`, `processors`, `disks`, `uploadSessions`, `MediaManager`, `MediaLibrary`, `AttachmentManager`, `UploadManager`, `ResumableUploadManager`, `MediaDeliveryHandler`, SPIs, errors |
25
25
  | `@adonis-agora/media/media_provider` | the service provider (binds `MediaManager`, mounts optional upload/TUS routes) |
26
+ | `@adonis-agora/media/dashboard_provider` | the embedded management-console provider (React SPA + JSON API) |
27
+ | `@adonis-agora/media/dashboard` | `defineConfig` + types for `config/media_dashboard.ts`, `DashboardService`, the session-auth helpers, `ObjectInsightProvider` |
26
28
  | `@adonis-agora/media/configure` | `node ace configure` hook |
27
29
  | `@adonis-agora/media/single-file` | `storeSingleFile` / `removeSingleFile` / `isSingleFileStoreAvailable` — lets other packages delegate single-file uploads (e.g. avatars) to media without a hard dependency |
28
30
  | `@adonis-agora/media/stores/lucid` | the Lucid `MediaStore` (`@adonisjs/lucid` peer) |
@@ -41,8 +43,10 @@ npm i @adonis-agora/media
41
43
  node ace configure @adonis-agora/media
42
44
  ```
43
45
 
44
- `configure` registers the provider, publishes `config/media.ts`, and publishes the `media` table
45
- migration (delete it if you only use the in-memory store; otherwise `node ace migration:run`).
46
+ `configure` registers the media provider **and the dashboard provider**, publishes `config/media.ts`
47
+ and `config/media_dashboard.ts`, and publishes the `media` table migration (delete it if you only use
48
+ the in-memory store; otherwise `node ace migration:run`). The management console is live at
49
+ `/media/dashboard` the moment your app boots — see [Dashboard](#dashboard).
46
50
 
47
51
  Optional peers, loaded lazily only when selected:
48
52
 
@@ -167,6 +171,42 @@ The bundled `disks.s3()` driver adds extended operations (copy/move/deleteMany/l
167
171
  native multipart over the optional AWS SDK peer. Drive it from the browser with
168
172
  [`@adonis-agora/media-react`](https://github.com/DavideCarvalho/adonis-media/tree/master/packages/react).
169
173
 
174
+ ## Dashboard
175
+
176
+ A management console — browse buckets, watch resumable uploads in progress, upload objects, and
177
+ copy/move/delete across buckets — ships **embedded** in this package: registering
178
+ `@adonis-agora/media/dashboard_provider` (done automatically by `node ace configure`) is all a
179
+ consuming app needs. No separate package install, no separate provider registration.
180
+
181
+ ```ts
182
+ // adonisrc.ts
183
+ providers: [
184
+ () => import('@adonis-agora/media/media_provider'),
185
+ () => import('@adonis-agora/media/dashboard_provider'),
186
+ ]
187
+ ```
188
+
189
+ ```ts
190
+ // config/media_dashboard.ts
191
+ import { defineConfig } from '@adonis-agora/media/dashboard'
192
+ import { middleware } from '#start/kernel'
193
+
194
+ export default defineConfig({
195
+ basePath: '/media/dashboard', // where the SPA mounts (default)
196
+ actions: true, // enable copy/move/delete (default: false — read-only)
197
+ disks: ['s3', 'backups'], // browsable disks (default: derived from media config)
198
+ middleware: middleware.auth(), // gate the whole console — SPA + API
199
+ })
200
+ ```
201
+
202
+ The console reads/writes through the real `@adonis-agora/media` surface (disk
203
+ `list`/`stat`/`copy`/`move`/`deleteMany`, the resumable session store, the `MediaStore`) — nothing
204
+ about storage is reimplemented. Full config reference, routes, and folder-operations semantics are
205
+ documented in [`@adonis-agora/media-dashboard`](https://github.com/DavideCarvalho/adonis-media/tree/master/packages/dashboard),
206
+ which is now the **build-time source** of the console's SPA bundle (embedded here at build time) and
207
+ remains installable **standalone** — its own provider is a thin delegate to this one, kept for hosts
208
+ that already register it directly. Don't register both providers in the same app.
209
+
170
210
  ## Diagnostics
171
211
 
172
212
  Lifecycle events (`attach`, `delete`, `conversion`, `attachment.create`, `attachment.delete`) are
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:JetBrains Mono,ui-monospace,SFMono-Regular,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-4{bottom:1rem}.left-1\/2{left:50%}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.z-10{z-index:10}.z-50{z-index:50}.z-\[60\]{z-index:60}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-px{margin-top:1px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-1\.5{height:.375rem}.h-14{height:3.5rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[86vh\]{height:86vh}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.max-h-40{max-height:10rem}.max-h-48{max-height:12rem}.max-h-56{max-height:14rem}.max-h-\[calc\(100vh-3rem\)\]{max-height:calc(100vh - 3rem)}.max-h-full{max-height:100%}.min-h-0{min-height:0px}.min-h-\[320px\]{min-height:320px}.w-14{width:3.5rem}.w-28{width:7rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-56{min-width:14rem}.min-w-\[150px\]{min-width:150px}.min-w-\[5rem\]{min-width:5rem}.max-w-5xl{max-width:64rem}.max-w-\[calc\(100vw-2rem\)\]{max-width:calc(100vw - 2rem)}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-\[110px_1fr\]{grid-template-columns:110px 1fr}.grid-cols-\[120px_1fr\]{grid-template-columns:120px 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-line-soft>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:color-mix(in srgb,var(--line-soft) calc(var(--tw-divide-opacity, 1) * 100%),transparent)}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-accent\/30{border-color:color-mix(in srgb,var(--accent) 30%,transparent)}.border-accent\/40{border-color:color-mix(in srgb,var(--accent) 40%,transparent)}.border-accent\/50{border-color:color-mix(in srgb,var(--accent) 50%,transparent)}.border-accent\/60{border-color:color-mix(in srgb,var(--accent) 60%,transparent)}.border-bad\/30{border-color:color-mix(in srgb,var(--bad) 30%,transparent)}.border-bad\/40{border-color:color-mix(in srgb,var(--bad) 40%,transparent)}.border-border{--tw-border-opacity: 1;border-color:color-mix(in srgb,var(--line) calc(var(--tw-border-opacity, 1) * 100%),transparent)}.border-transparent{border-color:transparent}.border-warn\/30{border-color:color-mix(in srgb,var(--warn) 30%,transparent)}.border-zinc-600{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.bg-accent\/10{background-color:color-mix(in srgb,var(--accent) 10%,transparent)}.bg-accent\/15{background-color:color-mix(in srgb,var(--accent) 15%,transparent)}.bg-accent\/5{background-color:color-mix(in srgb,var(--accent) 5%,transparent)}.bg-accent\/80{background-color:color-mix(in srgb,var(--accent) 80%,transparent)}.bg-bad\/10{background-color:color-mix(in srgb,var(--bad) 10%,transparent)}.bg-bad\/15{background-color:color-mix(in srgb,var(--bad) 15%,transparent)}.bg-black\/20{background-color:#0003}.bg-black\/30{background-color:#0000004d}.bg-black\/80{background-color:#000c}.bg-panel{--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--panel) calc(var(--tw-bg-opacity, 1) * 100%),transparent)}.bg-panel-2{--tw-bg-opacity: 1;background-color:color-mix(in srgb,var(--panel-2) calc(var(--tw-bg-opacity, 1) * 100%),transparent)}.bg-transparent{background-color:transparent}.bg-warn\/10{background-color:color-mix(in srgb,var(--warn) 10%,transparent)}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-zinc-800{--tw-bg-opacity: 1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.bg-zinc-800\/40{background-color:#27272a66}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity, 1))}.object-contain{-o-object-fit:contain;object-fit:contain}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pr-1\.5{padding-right:.375rem}.pr-2{padding-right:.5rem}.text-left{text-align:left}.text-center{text-align:center}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[9px\]{font-size:9px}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.leading-none{line-height:1}.tracking-\[0\.2em\]{letter-spacing:.2em}.tracking-normal{letter-spacing:0em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-accent{--tw-text-opacity: 1;color:color-mix(in srgb,var(--accent) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-accent\/80{color:color-mix(in srgb,var(--accent) 80%,transparent)}.text-bad{--tw-text-opacity: 1;color:color-mix(in srgb,var(--bad) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-foreground{--tw-text-opacity: 1;color:color-mix(in srgb,var(--text) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-sky-400{--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.text-warn{--tw-text-opacity: 1;color:color-mix(in srgb,var(--warn) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.text-zinc-100{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}.text-zinc-200{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.text-zinc-300{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.text-zinc-400{--tw-text-opacity: 1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.text-zinc-500{--tw-text-opacity: 1;color:rgb(113 113 122 / var(--tw-text-opacity, 1))}.text-zinc-600{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.text-zinc-700{--tw-text-opacity: 1;color:rgb(63 63 70 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.opacity-60{opacity:.6}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-inset{--tw-ring-inset: inset}.ring-accent\/50{--tw-ring-color: color-mix(in srgb, var(--accent) 50% , transparent)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-\[width\]{transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{--bg: #09090b;--panel: #0c0c0f;--panel-2: #101017;--line: #1c1c22;--line-soft: #16161a;--text: #e7e7ea;--muted: #76767f;--good: #34d399;--warn: #fbbf24;--bad: #f87171;--accent: #22d3ee}*{box-sizing:border-box}html,body,#root{height:100%}body{margin:0;background:var(--bg);color:var(--text);font-family:Space Grotesk,ui-sans-serif,system-ui,sans-serif;-webkit-font-smoothing:antialiased}.app-bg{position:fixed;top:0;right:0;bottom:0;left:0;z-index:0;pointer-events:none;background-image:radial-gradient(900px 400px at 78% -8%,color-mix(in srgb,var(--accent) 8%,transparent),transparent 70%),linear-gradient(to right,var(--line-soft) 1px,transparent 1px),linear-gradient(to bottom,var(--line-soft) 1px,transparent 1px);background-size:100% 100%,44px 44px,44px 44px;-webkit-mask-image:linear-gradient(to bottom,black,black 60%,transparent);mask-image:linear-gradient(to bottom,black,black 60%,transparent);opacity:.5}.mono{font-family:JetBrains Mono,ui-monospace,monospace}.tnum{font-variant-numeric:tabular-nums}.s-ok{color:var(--good)}.s-live{color:#60a5fa}.s-warn{color:var(--warn)}.s-error{color:var(--bad)}.s-info{color:#a78bfa}.s-idle{color:#71717a}.dot{width:7px;height:7px;border-radius:999px;background:currentColor;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 18%,transparent)}.pulse{animation:pulse 1.6s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.35}}@keyframes rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}.rise{animation:rise .32s cubic-bezier(.2,.7,.2,1) both}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:#26262c;border:3px solid var(--bg);border-radius:999px}.placeholder\:text-zinc-600::-moz-placeholder{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.placeholder\:text-zinc-600::placeholder{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.placeholder\:text-zinc-700::-moz-placeholder{--tw-text-opacity: 1;color:rgb(63 63 70 / var(--tw-text-opacity, 1))}.placeholder\:text-zinc-700::placeholder{--tw-text-opacity: 1;color:rgb(63 63 70 / var(--tw-text-opacity, 1))}.hover\:bg-accent\/20:hover{background-color:color-mix(in srgb,var(--accent) 20%,transparent)}.hover\:bg-bad\/20:hover{background-color:color-mix(in srgb,var(--bad) 20%,transparent)}.hover\:bg-zinc-800:hover{--tw-bg-opacity: 1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-800\/60:hover{background-color:#27272a99}.hover\:bg-zinc-900\/40:hover{background-color:#18181b66}.hover\:bg-zinc-900\/50:hover{background-color:#18181b80}.hover\:text-accent:hover{--tw-text-opacity: 1;color:color-mix(in srgb,var(--accent) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.hover\:text-bad:hover{--tw-text-opacity: 1;color:color-mix(in srgb,var(--bad) calc(var(--tw-text-opacity, 1) * 100%),transparent)}.hover\:text-sky-300:hover{--tw-text-opacity: 1;color:rgb(125 211 252 / var(--tw-text-opacity, 1))}.hover\:text-zinc-100:hover{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}.hover\:text-zinc-200:hover{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.hover\:text-zinc-300:hover{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.hover\:opacity-100:hover{opacity:1}.focus\:border-accent\/40:focus{border-color:color-mix(in srgb,var(--accent) 40%,transparent)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-ring\/40:focus-visible{--tw-ring-color: color-mix(in srgb, var(--accent) 40% , transparent)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-40:disabled{opacity:.4}@media(min-width:768px){.md\:grid-cols-\[220px_1fr\]{grid-template-columns:220px 1fr}}