Compare commits
31 Commits
a78a8fdef1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
0f90778b53
|
|||
|
dec32b9766
|
|||
|
64c13da521
|
|||
|
13f8c64f29
|
|||
|
27681c3ff5
|
|||
|
f83dca42ea
|
|||
|
94e550787e
|
|||
|
508d5a3525
|
|||
|
a42e02514e
|
|||
|
413f16fb6f
|
|||
|
c85cf06186
|
|||
|
63f9d3418c
|
|||
|
46460039af
|
|||
|
b9709dd655
|
|||
|
165eee9dd7
|
|||
|
fd28865071
|
|||
|
51afe1240d
|
|||
|
74909b9cd4
|
|||
|
bd4dd7ba23
|
|||
|
ae407c99c1
|
|||
|
d086bb61ed
|
|||
|
4d003329c7
|
|||
|
80ae32d799
|
|||
|
58ead2bb23
|
|||
|
5c3252746f
|
|||
|
68588f5d72
|
|||
|
ee0cb47e34
|
|||
|
c9866fd424
|
|||
|
b1ecb9f021
|
|||
|
da17ccc446
|
|||
|
73f8cb91c4
|
@@ -6,13 +6,13 @@ return {
|
|||||||
lua = { "stylua" },
|
lua = { "stylua" },
|
||||||
luau = { "stylua" },
|
luau = { "stylua" },
|
||||||
rust = { "rustfmt", lsp_format = "fallback" },
|
rust = { "rustfmt", lsp_format = "fallback" },
|
||||||
javascript = { "prettier" },
|
javascript = { "prettierd" },
|
||||||
typescript = { "prettier" },
|
typescript = { "prettierd" },
|
||||||
json = { "prettier" },
|
json = { "prettierd" },
|
||||||
tsx = { "prettier" },
|
tsx = { "prettierd" },
|
||||||
nix = { "nixfmt" },
|
nix = { "nixfmt" },
|
||||||
go = { "gofmt" },
|
go = { "gofmt" },
|
||||||
svelte = { "prettier" },
|
svelte = { "prettierd" },
|
||||||
},
|
},
|
||||||
format_on_save = {
|
format_on_save = {
|
||||||
-- These options will be passed to conform.format()
|
-- These options will be passed to conform.format()
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ local function setup_svelte()
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function setup_qml()
|
||||||
|
require("lspconfig").qmlls.setup({})
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
{
|
{
|
||||||
"neovim/nvim-lspconfig",
|
"neovim/nvim-lspconfig",
|
||||||
@@ -108,6 +112,7 @@ return {
|
|||||||
"clangd",
|
"clangd",
|
||||||
"cmake",
|
"cmake",
|
||||||
"cssls",
|
"cssls",
|
||||||
|
"qmlls",
|
||||||
},
|
},
|
||||||
automatic_enable = { exclude = { "luau_lsp", "lua_ls", "svelte" } },
|
automatic_enable = { exclude = { "luau_lsp", "lua_ls", "svelte" } },
|
||||||
})
|
})
|
||||||
@@ -117,6 +122,7 @@ return {
|
|||||||
setup_nix()
|
setup_nix()
|
||||||
setup_java()
|
setup_java()
|
||||||
setup_svelte()
|
setup_svelte()
|
||||||
|
setup_qml()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ return {
|
|||||||
"html",
|
"html",
|
||||||
"templ",
|
"templ",
|
||||||
"go",
|
"go",
|
||||||
|
"qmljs",
|
||||||
},
|
},
|
||||||
auto_install = true,
|
auto_install = true,
|
||||||
highlight = {
|
highlight = {
|
||||||
|
|||||||
1
.config/quickshell/.qmlls.ini
Symbolic link
1
.config/quickshell/.qmlls.ini
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/run/user/1000/quickshell/vfs/d51aaef3451280dfdf2f7cf03412fd13/.qmlls.ini
|
||||||
52
.config/quickshell/Bar.qml
Normal file
52
.config/quickshell/Bar.qml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
//qmllint disable unqualified
|
||||||
|
//qmllint disable unused-imports
|
||||||
|
//qmllint disable uncreatable-type
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import "components"
|
||||||
|
|
||||||
|
PanelWindow {
|
||||||
|
id: root
|
||||||
|
anchors.top: true
|
||||||
|
anchors.left: true
|
||||||
|
anchors.right: true
|
||||||
|
implicitHeight: 34
|
||||||
|
color: "#1a1b26"
|
||||||
|
required property var modelData
|
||||||
|
screen: modelData
|
||||||
|
|
||||||
|
property int fontSize: 18
|
||||||
|
property color colBg: "#1a1b26"
|
||||||
|
property color colFg: "#a9b1d6"
|
||||||
|
property color colMuted: "#444b6a"
|
||||||
|
property color colCyan: "#0db9d7"
|
||||||
|
property color colPurple: "#ad8ee6"
|
||||||
|
property color colRed: "#f7768e"
|
||||||
|
property color colYellow: "#e0af68"
|
||||||
|
property color colBlue: "#7aa2f7"
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredWidth: 30
|
||||||
|
Layout.preferredHeight: 28
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
Image {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: "file:///home/luca/dotfiles/.config/quickshell/icons/nixos.png"
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspaces {}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Clock {}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
.config/quickshell/components/Clock.qml
Normal file
34
.config/quickshell/components/Clock.qml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: clockRoot
|
||||||
|
implicitWidth: timeText.implicitWidth
|
||||||
|
implicitHeight: timeText.implicitHeight
|
||||||
|
|
||||||
|
property string dateTime: ""
|
||||||
|
|
||||||
|
function updateTime() {
|
||||||
|
dateTime = Qt.formatDateTime(new Date(), "ddd, MMM dd | HH:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 1000
|
||||||
|
running: true
|
||||||
|
repeat: true
|
||||||
|
triggeredOnStart: true
|
||||||
|
onTriggered: clockRoot.updateTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: timeText
|
||||||
|
text: clockRoot.dateTime
|
||||||
|
color: "#a9b1d6"
|
||||||
|
font {
|
||||||
|
pixelSize: 16
|
||||||
|
family: "Comic Relief"
|
||||||
|
bold: true
|
||||||
|
}
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
84
.config/quickshell/components/Workspaces.qml
Normal file
84
.config/quickshell/components/Workspaces.qml
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
//qmllint disable unqualified
|
||||||
|
//qmllint disable unused-imports
|
||||||
|
//qmllint disable uncreatable-type
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: Hyprland.workspaces.values
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
id: workspaceComponent
|
||||||
|
Layout.preferredWidth: 30
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
property bool isActive: modelData.focused
|
||||||
|
property int lastActive: 1
|
||||||
|
property int wsId: modelData.id
|
||||||
|
property bool isHovered: mouseHandler.containsMouse
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "active"
|
||||||
|
when: isActive
|
||||||
|
PropertyChanges {
|
||||||
|
target: workspaceComponent
|
||||||
|
color: Qt.rgba(1, 1, 1, 0.2)
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: underline
|
||||||
|
color: root.colPurple
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "hovered"
|
||||||
|
when: isHovered && !isActive
|
||||||
|
PropertyChanges {
|
||||||
|
target: workspaceComponent
|
||||||
|
color: Qt.rgba(1, 1, 1, 0.1)
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: underline
|
||||||
|
color: "#7aa2f7"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
transitions: Transition {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: modelData.id
|
||||||
|
color: isActive ? "#a9b1d6" : "#7aa2f7"
|
||||||
|
font {
|
||||||
|
pixelSize: root.fontSize
|
||||||
|
bold: true
|
||||||
|
family: "Comic Relief"
|
||||||
|
}
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: underline
|
||||||
|
width: 30
|
||||||
|
height: 3
|
||||||
|
color: root.colBg
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseHandler
|
||||||
|
hoverEnabled: true
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: Hyprland.dispatch("workspace " + modelData.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
.config/quickshell/icons/nixos.png
Normal file
BIN
.config/quickshell/icons/nixos.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
15
.config/quickshell/shell.qml
Normal file
15
.config/quickshell/shell.qml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//qmllint disable unqualified
|
||||||
|
//qmllint disable unused-imports
|
||||||
|
//qmllint disable uncreatable-type
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
Scope {
|
||||||
|
Variants {
|
||||||
|
model: Quickshell.screens
|
||||||
|
delegate: Component {
|
||||||
|
Bar {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
nix/flake.lock
generated
60
nix/flake.lock
generated
@@ -81,6 +81,27 @@
|
|||||||
},
|
},
|
||||||
"parent": []
|
"parent": []
|
||||||
},
|
},
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1768632427,
|
||||||
|
"narHash": "sha256-Y6kP10exkn5UiK9ead2Gky8TFsFZSsyT4f69DMKm0Wo=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "edd560269f0d9ad75bd3da292ce4d9d27efdd22a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@@ -186,17 +207,56 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"quickshell": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1768689040,
|
||||||
|
"narHash": "sha256-Tlnr5BulJcMers/cb+YvmBQW4nKHjdKo9loInJkyO2k=",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"rev": "7a427ce1979ce7447e885c4f30129b40f3d466f5",
|
||||||
|
"revCount": 729,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"custom-fonts": "custom-fonts",
|
"custom-fonts": "custom-fonts",
|
||||||
|
"fenix": "fenix",
|
||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"nixos-wsl": "nixos-wsl",
|
"nixos-wsl": "nixos-wsl",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_2",
|
||||||
"nixpkgs-before": "nixpkgs-before",
|
"nixpkgs-before": "nixpkgs-before",
|
||||||
|
"quickshell": "quickshell",
|
||||||
"sops-nix": "sops-nix",
|
"sops-nix": "sops-nix",
|
||||||
"status-bar": "status-bar"
|
"status-bar": "status-bar"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1768468158,
|
||||||
|
"narHash": "sha256-DfifO/Se9ogmp5rxe/OwmRIz20/w6BsbWC1s4kL1Bzc=",
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "adbff8baedae53f9955fe60c0d470ecd77b4f548",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sops-nix": {
|
"sops-nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|||||||
@@ -21,6 +21,15 @@
|
|||||||
url = "github:Mic92/sops-nix";
|
url = "github:Mic92/sops-nix";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fenix = {
|
||||||
|
url = "github:nix-community/fenix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
quickshell = {
|
||||||
|
url = "git+https://git.outfoxxed.me/outfoxxed/quickshell";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
@@ -70,6 +79,7 @@
|
|||||||
inherit inputs;
|
inherit inputs;
|
||||||
meta = {
|
meta = {
|
||||||
hostname = host.name;
|
hostname = host.name;
|
||||||
|
architecture = host.architecture;
|
||||||
};
|
};
|
||||||
pkgs-before = import inputs.nixpkgs-before { system = host.architecture; };
|
pkgs-before = import inputs.nixpkgs-before { system = host.architecture; };
|
||||||
};
|
};
|
||||||
|
|||||||
1132
nix/homelab/Cargo.lock
generated
1132
nix/homelab/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,12 @@ tokio = { version = "1.49.0", features = ["macros", "rt"] }
|
|||||||
toml = { version = "0.9.10", optional = true }
|
toml = { version = "0.9.10", optional = true }
|
||||||
urlencoding = "2"
|
urlencoding = "2"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
".",
|
||||||
|
"cli"
|
||||||
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["file-config"]
|
default = ["file-config"]
|
||||||
file-config = ["dep:toml"]
|
file-config = ["dep:toml"]
|
||||||
|
|||||||
21
nix/homelab/cli/Cargo.toml
Normal file
21
nix/homelab/cli/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[package]
|
||||||
|
name = "homelab-cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.100"
|
||||||
|
askama = "0.15.1"
|
||||||
|
chrono = "0.4.43"
|
||||||
|
clap = { version = "4.5.54", features = ["derive"] }
|
||||||
|
dialoguer = "0.12.0"
|
||||||
|
futures = "0.3.31"
|
||||||
|
indicatif = "0.18.3"
|
||||||
|
k8s-openapi = { version = "0.27.0", features = ["latest", "schemars", "v1_35"] }
|
||||||
|
kube = { version = "3.0.0", features = ["runtime", "derive"] }
|
||||||
|
schemars = "1.2.0"
|
||||||
|
serde_json = "1.0.149"
|
||||||
|
serde_yaml = "0.9.34"
|
||||||
|
thiserror = "2.0.18"
|
||||||
|
thiserror-ext = "0.3.0"
|
||||||
|
tokio = { version = "1.49.0", features = ["macros", "rt"] }
|
||||||
3
nix/homelab/cli/askama.toml
Normal file
3
nix/homelab/cli/askama.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[[escaper]]
|
||||||
|
path = "askama::filters::Text"
|
||||||
|
extensions = ["yaml"]
|
||||||
144
nix/homelab/cli/src/commands/minecraft.rs
Normal file
144
nix/homelab/cli/src/commands/minecraft.rs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
use askama::Template;
|
||||||
|
use clap::{Args, Subcommand};
|
||||||
|
use futures::{AsyncBufReadExt, StreamExt, TryStreamExt};
|
||||||
|
use k8s_openapi::api::apps::v1::Deployment;
|
||||||
|
use k8s_openapi::api::batch::v1::Job;
|
||||||
|
use k8s_openapi::api::core::v1::Pod;
|
||||||
|
use kube::api::{Api, LogParams, Patch, PatchParams, PostParams};
|
||||||
|
use kube::runtime::{WatchStreamExt, watcher};
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::State;
|
||||||
|
use crate::error::{ErrorKind, Result};
|
||||||
|
use crate::reporter::Reporter;
|
||||||
|
|
||||||
|
const NAMESPACE: &str = "minecraft";
|
||||||
|
|
||||||
|
#[derive(Debug, Args)]
|
||||||
|
pub struct MinecraftCommand {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: MinecraftSubcommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
enum MinecraftSubcommand {
|
||||||
|
/// Backup a minecraft world
|
||||||
|
Backup {
|
||||||
|
/// the world to backup
|
||||||
|
#[arg(short, long)]
|
||||||
|
world: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "backup-job.yaml")]
|
||||||
|
struct BackupJobTemplate<'a> {
|
||||||
|
world: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MinecraftCommand {
|
||||||
|
pub async fn run(&self, state: State) -> Result<()> {
|
||||||
|
match &self.command {
|
||||||
|
MinecraftSubcommand::Backup { world } => backup_world(state, world).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn backup_world(state: State, world: &str) -> Result<()> {
|
||||||
|
let reporter = Reporter::new();
|
||||||
|
let job_name = format!("minecraft-{}-backup", world);
|
||||||
|
|
||||||
|
reporter.log(format!("Scaling deployment minecraft-{world}"));
|
||||||
|
scale_deployment(&state.client, NAMESPACE, &format!("minecraft-{world}"), 0).await?;
|
||||||
|
|
||||||
|
reporter.status("Creating backup job...");
|
||||||
|
|
||||||
|
let job = build_backup_job(world)?;
|
||||||
|
let jobs: Api<Job> = Api::namespaced(state.client.clone(), NAMESPACE);
|
||||||
|
jobs.create(&PostParams::default(), &job).await?;
|
||||||
|
|
||||||
|
reporter.status("Waiting for pod to start...");
|
||||||
|
|
||||||
|
let pods: Api<Pod> = Api::namespaced(state.client.clone(), NAMESPACE);
|
||||||
|
let pod_name = wait_for_job_pod(&pods, &job_name).await?;
|
||||||
|
|
||||||
|
reporter.status("Running backup...");
|
||||||
|
|
||||||
|
stream_pod_logs(&pods, &pod_name, &reporter).await?;
|
||||||
|
|
||||||
|
let job = jobs.get(&job_name).await?;
|
||||||
|
let status = job.status.as_ref();
|
||||||
|
let succeeded = status.and_then(|s| s.succeeded).unwrap_or(0);
|
||||||
|
let failed = status.and_then(|s| s.failed).unwrap_or(0);
|
||||||
|
|
||||||
|
reporter.log(format!("Scaling deployment minecraft-{world}, replicas: 1"));
|
||||||
|
scale_deployment(&state.client, NAMESPACE, &format!("minecraft-{world}"), 1).await?;
|
||||||
|
if succeeded > 0 {
|
||||||
|
reporter.success("Backup complete");
|
||||||
|
Ok(())
|
||||||
|
} else if failed > 0 {
|
||||||
|
reporter.fail("Backup job failed");
|
||||||
|
Err(ErrorKind::BackupFailed("Job failed".to_string()).into())
|
||||||
|
} else {
|
||||||
|
reporter.fail("Backup job status unknown");
|
||||||
|
Err(ErrorKind::BackupFailed("Unknown status".to_string()).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn scale_deployment(
|
||||||
|
client: &kube::Client,
|
||||||
|
namespace: &str,
|
||||||
|
name: &str,
|
||||||
|
replicas: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let deployments: Api<Deployment> = Api::namespaced(client.clone(), namespace);
|
||||||
|
let patch = json!({ "spec": { "replicas": replicas } });
|
||||||
|
deployments
|
||||||
|
.patch(name, &PatchParams::default(), &Patch::Merge(&patch))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn wait_for_job_pod(pods: &Api<Pod>, job_name: &str) -> Result<String> {
|
||||||
|
let label_selector = format!("job-name={}", job_name);
|
||||||
|
let config = watcher::Config::default().labels(&label_selector);
|
||||||
|
|
||||||
|
let mut stream = watcher(pods.clone(), config).applied_objects().boxed();
|
||||||
|
|
||||||
|
while let Some(pod) = stream.try_next().await? {
|
||||||
|
let name = pod.metadata.name.as_deref().unwrap_or_default();
|
||||||
|
let phase = pod
|
||||||
|
.status
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|s| s.phase.as_deref())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
if phase == "Running" || phase == "Succeeded" || phase == "Failed" {
|
||||||
|
return Ok(name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(ErrorKind::BackupFailed("Pod never started".to_string()).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_backup_job(world: &str) -> Result<Job> {
|
||||||
|
let template = BackupJobTemplate { world };
|
||||||
|
let yaml = template.render()?;
|
||||||
|
Ok(serde_yaml::from_str(&yaml)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn stream_pod_logs(pods: &Api<Pod>, pod_name: &str, reporter: &Reporter) -> Result<()> {
|
||||||
|
let params = LogParams {
|
||||||
|
follow: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let stream = pods.log_stream(pod_name, ¶ms).await?;
|
||||||
|
let mut lines = stream.lines();
|
||||||
|
|
||||||
|
while let Some(line) = lines.try_next().await? {
|
||||||
|
reporter.log_event(&line);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
8
nix/homelab/cli/src/commands/mod.rs
Normal file
8
nix/homelab/cli/src/commands/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use clap::Subcommand;
|
||||||
|
mod minecraft;
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug)]
|
||||||
|
pub enum Commands {
|
||||||
|
/// minecraft management
|
||||||
|
Minecraft(minecraft::MinecraftCommand),
|
||||||
|
}
|
||||||
20
nix/homelab/cli/src/error.rs
Normal file
20
nix/homelab/cli/src/error.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug, thiserror_ext::Box)]
|
||||||
|
#[thiserror_ext(newtype(name = Error))]
|
||||||
|
pub enum ErrorKind {
|
||||||
|
#[error("kube error: {0}")]
|
||||||
|
Kube(#[from] kube::Error),
|
||||||
|
#[error("watcher error: {0}")]
|
||||||
|
Watcher(#[from] kube::runtime::watcher::Error),
|
||||||
|
#[error("io error: {0}")]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[error("backup failed: {0}")]
|
||||||
|
BackupFailed(String),
|
||||||
|
#[error("template error: {0}")]
|
||||||
|
Template(#[from] askama::Error),
|
||||||
|
#[error("error deserializing yaml: {0}")]
|
||||||
|
Yaml(#[from] serde_yaml::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
57
nix/homelab/cli/src/main.rs
Normal file
57
nix/homelab/cli/src/main.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
mod commands;
|
||||||
|
mod error;
|
||||||
|
mod reporter;
|
||||||
|
|
||||||
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
|
use clap::{CommandFactory, Parser};
|
||||||
|
|
||||||
|
use crate::{commands::Commands, error::Result};
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(version, long_about = "homelab cli")]
|
||||||
|
struct Cli {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Option<Commands>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AppState {
|
||||||
|
client: kube::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct State(Arc<AppState>);
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub fn new(inner: AppState) -> Self {
|
||||||
|
Self(Arc::new(inner))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for State {
|
||||||
|
type Target = AppState;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppState {
|
||||||
|
pub async fn new() -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
client: kube::Client::try_default().await?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main(flavor = "current_thread")]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
let cli = Cli::parse();
|
||||||
|
let app_state = State::new(AppState::new().await?);
|
||||||
|
|
||||||
|
match cli.command {
|
||||||
|
Some(Commands::Minecraft(cmd)) => cmd.run(app_state.clone()).await?,
|
||||||
|
_ => Cli::command().print_long_help()?,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
52
nix/homelab/cli/src/reporter.rs
Normal file
52
nix/homelab/cli/src/reporter.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
|
|
||||||
|
pub struct Reporter {
|
||||||
|
spinner: ProgressBar,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const TICK_CHARS: &str = "⣷⣯⣟⡿⢿⣻⣽⣾";
|
||||||
|
|
||||||
|
impl Reporter {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let spinner = ProgressBar::new_spinner();
|
||||||
|
spinner.set_style(
|
||||||
|
ProgressStyle::with_template(
|
||||||
|
"{prefix:.dim}{msg:>8.214/yellow} {spinner} [{elapsed_precise}]",
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.tick_chars(TICK_CHARS),
|
||||||
|
);
|
||||||
|
spinner.enable_steady_tick(std::time::Duration::from_millis(100));
|
||||||
|
Self { spinner }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status(&self, msg: impl Into<String>) {
|
||||||
|
self.spinner.set_message(msg.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_event(&self, line: &str) {
|
||||||
|
self.spinner.suspend(|| {
|
||||||
|
println!(" │ {}", line);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log<T: Display>(&self, text: T) {
|
||||||
|
self.spinner.suspend(|| println!("{}", text))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn success(&self, msg: &str) {
|
||||||
|
self.spinner.finish_with_message(format!("✓ {}", msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fail(&self, msg: &str) {
|
||||||
|
self.spinner.finish_with_message(format!("✗ {}", msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Reporter {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
40
nix/homelab/cli/templates/backup-job.yaml
Normal file
40
nix/homelab/cli/templates/backup-job.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: minecraft-{{ world }}-backup
|
||||||
|
namespace: minecraft
|
||||||
|
labels:
|
||||||
|
app: minecraft-backup
|
||||||
|
world: {{ world }}
|
||||||
|
spec:
|
||||||
|
ttlSecondsAfterFinished: 300
|
||||||
|
backoffLimit: 0
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
job-name: minecraft-{{ world }}-backup
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
containers:
|
||||||
|
- name: backup
|
||||||
|
image: busybox
|
||||||
|
command:
|
||||||
|
- "sh"
|
||||||
|
- "-c"
|
||||||
|
- |
|
||||||
|
tar -czvf /backups/minecraft-{{ world }}-manual.tar.gz -C /data .
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
readOnly: true
|
||||||
|
- name: backups
|
||||||
|
mountPath: /backups
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: minecraft-{{ world }}-datadir
|
||||||
|
readOnly: true
|
||||||
|
- name: backups
|
||||||
|
nfs:
|
||||||
|
server: 192.168.27.2
|
||||||
|
path: /backup/minecraft
|
||||||
1
nix/homelab/cli/templates/sync.yaml
Normal file
1
nix/homelab/cli/templates/sync.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
@@ -101,6 +101,13 @@ routes = [
|
|||||||
service = "prometheus-stack-grafana",
|
service = "prometheus-stack-grafana",
|
||||||
port = 80,
|
port = 80,
|
||||||
private = true
|
private = true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "mesh",
|
||||||
|
namespace = "networking",
|
||||||
|
service = "headscale",
|
||||||
|
port = 8080,
|
||||||
|
private = false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
26
nix/homelab/frontend/.gitignore
vendored
26
nix/homelab/frontend/.gitignore
vendored
@@ -1,26 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
/.svelte-kit
|
|
||||||
build
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
*.local
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
|
|
||||||
"tailwindStylesheet": "./src/routes/layout.css"
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
# Svelte + TS + Vite
|
|
||||||
|
|
||||||
This template should help get you started developing with Svelte and TypeScript in Vite.
|
|
||||||
|
|
||||||
## Recommended IDE Setup
|
|
||||||
|
|
||||||
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
|
|
||||||
|
|
||||||
## Need an official Svelte framework?
|
|
||||||
|
|
||||||
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
|
|
||||||
|
|
||||||
## Technical considerations
|
|
||||||
|
|
||||||
**Why use this over SvelteKit?**
|
|
||||||
|
|
||||||
- It brings its own routing solution which might not be preferable for some users.
|
|
||||||
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
|
|
||||||
|
|
||||||
This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
|
|
||||||
|
|
||||||
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
|
|
||||||
|
|
||||||
**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
|
|
||||||
|
|
||||||
Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
|
|
||||||
|
|
||||||
**Why include `.vscode/extensions.json`?**
|
|
||||||
|
|
||||||
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
|
|
||||||
|
|
||||||
**Why enable `allowJs` in the TS template?**
|
|
||||||
|
|
||||||
While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
|
|
||||||
|
|
||||||
**Why is HMR not preserving my local component state?**
|
|
||||||
|
|
||||||
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
|
|
||||||
|
|
||||||
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// store.ts
|
|
||||||
// An extremely simple external store
|
|
||||||
import { writable } from 'svelte/store'
|
|
||||||
export default writable(0)
|
|
||||||
```
|
|
||||||
@@ -1,309 +0,0 @@
|
|||||||
{
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"configVersion": 1,
|
|
||||||
"workspaces": {
|
|
||||||
"": {
|
|
||||||
"name": "minecraft",
|
|
||||||
"dependencies": {
|
|
||||||
"@lucide/svelte": "^0.562.0",
|
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
|
||||||
"@tanstack/svelte-query": "^6.0.14",
|
|
||||||
"@tanstack/svelte-query-devtools": "^6.0.3",
|
|
||||||
"bits-ui": "^2.15.4",
|
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"tailwindcss": "^4.1.18",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@sveltejs/adapter-static": "^3.0.10",
|
|
||||||
"@sveltejs/kit": "^2.49.1",
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
||||||
"@types/node": "^24.10.1",
|
|
||||||
"prettier": "^3.7.4",
|
|
||||||
"prettier-plugin-svelte": "^3.4.1",
|
|
||||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
||||||
"svelte": "^5.43.8",
|
|
||||||
"svelte-check": "^4.3.4",
|
|
||||||
"typescript": "~5.9.3",
|
|
||||||
"vite": "^7.2.5",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"vite": "npm:rolldown-vite@7.2.5",
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
|
||||||
|
|
||||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
|
||||||
|
|
||||||
"@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="],
|
|
||||||
|
|
||||||
"@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="],
|
|
||||||
|
|
||||||
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
|
|
||||||
|
|
||||||
"@internationalized/date": ["@internationalized/date@3.10.1", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA=="],
|
|
||||||
|
|
||||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
|
||||||
|
|
||||||
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
|
||||||
|
|
||||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
|
||||||
|
|
||||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
|
||||||
|
|
||||||
"@lucide/svelte": ["@lucide/svelte@0.562.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-wDMULwtTFN2Sc/TFBm6gfuVCNb4Y5P9LDrwxNnUbV52+IEU7NXZmvxwXoz+vrrpad6Xupq+Hw5eUlqIHEGhouw=="],
|
|
||||||
|
|
||||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
|
||||||
|
|
||||||
"@oxc-project/runtime": ["@oxc-project/runtime@0.97.0", "", {}, "sha512-yH0zw7z+jEws4dZ4IUKoix5Lh3yhqIJWF9Dc8PWvhpo7U7O+lJrv7ZZL4BeRO0la8LBQFwcCewtLBnVV7hPe/w=="],
|
|
||||||
|
|
||||||
"@oxc-project/types": ["@oxc-project/types@0.97.0", "", {}, "sha512-lxmZK4xFrdvU0yZiDwgVQTCvh2gHWBJCBk5ALsrtsBWhs0uDIi+FTOnXRQeQfs304imdvTdaakT/lqwQ8hkOXQ=="],
|
|
||||||
|
|
||||||
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.50", "", { "os": "android", "cpu": "arm64" }, "sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.50", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.50", "", { "os": "darwin", "cpu": "x64" }, "sha512-fFXDjXnuX7/gQZQm/1FoivVtRcyAzdjSik7Eo+9iwPQ9EgtA5/nB2+jmbzaKtMGG3q+BnZbdKHCtOacmNrkIDA=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.50", "", { "os": "freebsd", "cpu": "x64" }, "sha512-F1b6vARy49tjmT/hbloplzgJS7GIvwWZqt+tAHEstCh0JIh9sa8FAMVqEmYxDviqKBaAI8iVvUREm/Kh/PD26Q=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50", "", { "os": "linux", "cpu": "arm" }, "sha512-U6cR76N8T8M6lHj7EZrQ3xunLPxSvYYxA8vJsBKZiFZkT8YV4kjgCO3KwMJL0NOjQCPGKyiXO07U+KmJzdPGRw=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50", "", { "os": "linux", "cpu": "arm64" }, "sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.50", "", { "os": "linux", "cpu": "arm64" }, "sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.50", "", { "os": "linux", "cpu": "x64" }, "sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.50", "", { "os": "linux", "cpu": "x64" }, "sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.50", "", { "os": "none", "cpu": "arm64" }, "sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.50", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.7" }, "cpu": "none" }, "sha512-nmCN0nIdeUnmgeDXiQ+2HU6FT162o+rxnF7WMkBm4M5Ds8qTU7Dzv2Wrf22bo4ftnlrb2hKK6FSwAJSAe2FWLg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50", "", { "os": "win32", "cpu": "arm64" }, "sha512-7kcNLi7Ua59JTTLvbe1dYb028QEPaJPJQHqkmSZ5q3tJueUeb6yjRtx8mw4uIqgWZcnQHAR3PrLN4XRJxvgIkA=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50", "", { "os": "win32", "cpu": "ia32" }, "sha512-lL70VTNvSCdSZkDPPVMwWn/M2yQiYvSoXw9hTLgdIWdUfC3g72UaruezusR6ceRuwHCY1Ayu2LtKqXkBO5LIwg=="],
|
|
||||||
|
|
||||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.50", "", { "os": "win32", "cpu": "x64" }, "sha512-4qU4x5DXWB4JPjyTne/wBNPqkbQU8J45bl21geERBKtEittleonioACBL1R0PsBu0Aq21SwMK5a9zdBkWSlQtQ=="],
|
|
||||||
|
|
||||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.50", "", {}, "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA=="],
|
|
||||||
|
|
||||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
||||||
|
|
||||||
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.8", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA=="],
|
|
||||||
|
|
||||||
"@sveltejs/adapter-static": ["@sveltejs/adapter-static@3.0.10", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew=="],
|
|
||||||
|
|
||||||
"@sveltejs/kit": ["@sveltejs/kit@2.49.4", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-JFtOqDoU0DI/+QSG8qnq5bKcehVb3tCHhOG4amsSYth5/KgO4EkJvi42xSAiyKmXAAULW1/Zdb6lkgGEgSxdZg=="],
|
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.4", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA=="],
|
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.2", "", { "dependencies": { "obug": "^2.1.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig=="],
|
|
||||||
|
|
||||||
"@swc/helpers": ["@swc/helpers@0.5.18", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.18", "", { "os": "android", "cpu": "arm64" }, "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.18", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18", "", { "os": "linux", "cpu": "arm" }, "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.18", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.18", "", { "os": "win32", "cpu": "x64" }, "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q=="],
|
|
||||||
|
|
||||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="],
|
|
||||||
|
|
||||||
"@tanstack/query-core": ["@tanstack/query-core@5.90.16", "", {}, "sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww=="],
|
|
||||||
|
|
||||||
"@tanstack/query-devtools": ["@tanstack/query-devtools@5.92.0", "", {}, "sha512-N8D27KH1vEpVacvZgJL27xC6yPFUy0Zkezn5gnB3L3gRCxlDeSuiya7fKge8Y91uMTnC8aSxBQhcK6ocY7alpQ=="],
|
|
||||||
|
|
||||||
"@tanstack/svelte-query": ["@tanstack/svelte-query@6.0.14", "", { "dependencies": { "@tanstack/query-core": "5.90.16" }, "peerDependencies": { "svelte": "^5.25.0" } }, "sha512-gKuHxbyGP2pCQgE/Px9FtlyFmHTt0OV5xTrKrk7PMKGkv3LPWTTwDb7xlMDe1V7U2K5ci+jq1j3HsuTPqIZxjA=="],
|
|
||||||
|
|
||||||
"@tanstack/svelte-query-devtools": ["@tanstack/svelte-query-devtools@6.0.3", "", { "dependencies": { "@tanstack/query-devtools": "5.92.0", "esm-env": "^1.2.1" }, "peerDependencies": { "@tanstack/svelte-query": "^6.0.12", "svelte": "^5.25.0" } }, "sha512-AHc/vPiUWeMFXKvtrlZot7wIlsIm4z5vd0wDeQUKwE5XTfZODu0no1A4UCLzVnY2WpbBpakIEUMH+PmSMwYXKg=="],
|
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
|
||||||
|
|
||||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.10.7", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-+054pVMzVTmRQV8BhpGv3UyfZ2Llgl8rdpDTon+cUH9+na0ncBVXj3wTUKh14+Kiz18ziM3b4ikpP5/Pc0rQEQ=="],
|
|
||||||
|
|
||||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
|
||||||
|
|
||||||
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
|
|
||||||
|
|
||||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
|
||||||
|
|
||||||
"bits-ui": ["bits-ui@2.15.4", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-7H9YUfp03KOk1LVDh8wPYSRPxlZgG/GRWLNSA8QC73/8Z8ytun+DWJhIuibyFyz7A0cP/RANVcB4iDrbY8q+Og=="],
|
|
||||||
|
|
||||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
|
||||||
|
|
||||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
|
||||||
|
|
||||||
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
|
|
||||||
|
|
||||||
"date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
|
|
||||||
|
|
||||||
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
|
|
||||||
|
|
||||||
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
||||||
|
|
||||||
"devalue": ["devalue@5.6.1", "", {}, "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A=="],
|
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="],
|
|
||||||
|
|
||||||
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
|
|
||||||
|
|
||||||
"esrap": ["esrap@2.2.1", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg=="],
|
|
||||||
|
|
||||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
|
||||||
|
|
||||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
|
||||||
|
|
||||||
"inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
|
|
||||||
|
|
||||||
"is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],
|
|
||||||
|
|
||||||
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
|
||||||
|
|
||||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
|
||||||
|
|
||||||
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
|
|
||||||
|
|
||||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
|
|
||||||
|
|
||||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
|
|
||||||
|
|
||||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
|
|
||||||
|
|
||||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
|
|
||||||
|
|
||||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
|
|
||||||
|
|
||||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
|
|
||||||
|
|
||||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
|
|
||||||
|
|
||||||
"locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="],
|
|
||||||
|
|
||||||
"lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="],
|
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
|
||||||
|
|
||||||
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
|
||||||
|
|
||||||
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
|
||||||
|
|
||||||
"obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
|
|
||||||
|
|
||||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
||||||
|
|
||||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
|
||||||
|
|
||||||
"prettier": ["prettier@3.7.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA=="],
|
|
||||||
|
|
||||||
"prettier-plugin-svelte": ["prettier-plugin-svelte@3.4.1", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "sha512-xL49LCloMoZRvSwa6IEdN2GV6cq2IqpYGstYtMT+5wmml1/dClEoI0MZR78MiVPpu6BdQFfN0/y73yO6+br5Pg=="],
|
|
||||||
|
|
||||||
"prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.7.2", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-svelte"] }, "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA=="],
|
|
||||||
|
|
||||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
|
||||||
|
|
||||||
"rolldown": ["rolldown@1.0.0-beta.50", "", { "dependencies": { "@oxc-project/types": "=0.97.0", "@rolldown/pluginutils": "1.0.0-beta.50" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-x64": "1.0.0-beta.50", "@rolldown/binding-freebsd-x64": "1.0.0-beta.50", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.50", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.50", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.50", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.50", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.50" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A=="],
|
|
||||||
|
|
||||||
"runed": ["runed@0.35.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0" }, "optionalPeers": ["@sveltejs/kit"] }, "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q=="],
|
|
||||||
|
|
||||||
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
|
|
||||||
|
|
||||||
"set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="],
|
|
||||||
|
|
||||||
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
||||||
|
|
||||||
"style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
|
|
||||||
|
|
||||||
"svelte": ["svelte@5.46.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.5.0", "esm-env": "^1.2.1", "esrap": "^2.2.1", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-ynjfCHD3nP2el70kN5Pmg37sSi0EjOm9FgHYQdC4giWG/hzO3AatzXXJJgP305uIhGQxSufJLuYWtkY8uK/8RA=="],
|
|
||||||
|
|
||||||
"svelte-check": ["svelte-check@4.3.5", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-e4VWZETyXaKGhpkxOXP+B/d0Fp/zKViZoJmneZWe/05Y2aqSKj3YN2nLfYPJBQ87WEiY4BQCQ9hWGu9mPT1a1Q=="],
|
|
||||||
|
|
||||||
"svelte-toolbelt": ["svelte-toolbelt@0.10.6", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.35.1", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.30.2" } }, "sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ=="],
|
|
||||||
|
|
||||||
"tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
|
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
|
|
||||||
|
|
||||||
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
|
||||||
|
|
||||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
||||||
|
|
||||||
"vite": ["rolldown-vite@7.2.5", "", { "dependencies": { "@oxc-project/runtime": "0.97.0", "fdir": "^6.5.0", "lightningcss": "^1.30.2", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-beta.50", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "esbuild": "^0.25.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA=="],
|
|
||||||
|
|
||||||
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
|
|
||||||
|
|
||||||
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "homelab",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build",
|
|
||||||
"preview": "vite preview",
|
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
||||||
"format": "prettier --write .",
|
|
||||||
"lint": "prettier --check ."
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
||||||
"@sveltejs/kit": "^2.49.1",
|
|
||||||
"@sveltejs/adapter-static": "^3.0.10",
|
|
||||||
"@types/node": "^24.10.1",
|
|
||||||
"prettier": "^3.7.4",
|
|
||||||
"prettier-plugin-svelte": "^3.4.1",
|
|
||||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
||||||
"svelte": "^5.43.8",
|
|
||||||
"svelte-check": "^4.3.4",
|
|
||||||
"typescript": "~5.9.3",
|
|
||||||
"vite": "npm:rolldown-vite@7.2.5"
|
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"vite": "npm:rolldown-vite@7.2.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@lucide/svelte": "^0.562.0",
|
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
|
||||||
"@tanstack/svelte-query": "^6.0.14",
|
|
||||||
"@tanstack/svelte-query-devtools": "^6.0.3",
|
|
||||||
"bits-ui": "^2.15.4",
|
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"tailwindcss": "^4.1.18"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
nix/homelab/frontend/src/app.d.ts
vendored
13
nix/homelab/frontend/src/app.d.ts
vendored
@@ -1,13 +0,0 @@
|
|||||||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
|
||||||
// for information about these interfaces
|
|
||||||
declare global {
|
|
||||||
namespace App {
|
|
||||||
// interface Error {}
|
|
||||||
// interface Locals {}
|
|
||||||
// interface PageData {}
|
|
||||||
// interface PageState {}
|
|
||||||
// interface Platform {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {};
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
||||||
<!-- <link rel="stylesheet" href="/src/app.css" /> -->
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<!-- <title>Homelab</title> -->
|
|
||||||
%sveltekit.head%
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body data-sveltekit-preload-data="hover">
|
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="26.6" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 308"><path fill="#FF3E00" d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056a86.566 86.566 0 0 0 8.536 55.576a82.425 82.425 0 0 0-12.296 30.719a87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057a86.601 86.601 0 0 0-8.53-55.577a82.409 82.409 0 0 0 12.29-30.718a87.573 87.573 0 0 0-14.963-66.244"></path><path fill="#FFF" d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85a49.978 49.978 0 0 1 1.713-6.693l1.35-4.115l3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808l-.245 2.659a16.067 16.067 0 0 0 2.89 10.656a17.143 17.143 0 0 0 18.397 6.828a15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977a15.923 15.923 0 0 0-2.713-12.011a17.156 17.156 0 0 0-18.404-6.832a15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849a49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85a50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116l-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809l.246-2.658a16.099 16.099 0 0 0-2.89-10.656a17.143 17.143 0 0 0-18.398-6.828a15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975a15.9 15.9 0 0 0 2.709 12.012a17.156 17.156 0 0 0 18.404 6.832a15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848a49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -1,30 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { LoaderCircle } from "@lucide/svelte";
|
|
||||||
import type { ButtonRootProps } from "bits-ui";
|
|
||||||
import { Button } from "bits-ui";
|
|
||||||
type Props = ButtonRootProps & {
|
|
||||||
loading?: boolean;
|
|
||||||
["loading-overwrite"]?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
|
||||||
children,
|
|
||||||
loading,
|
|
||||||
disabled,
|
|
||||||
"loading-overwrite": loadingOverwite = true,
|
|
||||||
...props
|
|
||||||
}: Props = $props();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Button.Root disabled={loading || disabled} {...props}>
|
|
||||||
{#if loading}
|
|
||||||
<span class="flex gap-2">
|
|
||||||
{#if !loadingOverwite}
|
|
||||||
{@render children?.()}
|
|
||||||
{/if}
|
|
||||||
<LoaderCircle class="animate-spin" />
|
|
||||||
</span>
|
|
||||||
{:else}
|
|
||||||
{@render children?.()}
|
|
||||||
{/if}
|
|
||||||
</Button.Root>
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { Button } from "bits-ui";
|
|
||||||
|
|
||||||
function syncCreativeWorld() {
|
|
||||||
console.log("Syncing creative world...");
|
|
||||||
}
|
|
||||||
|
|
||||||
function backupMainWorld() {
|
|
||||||
console.log("Backing up main world...");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="flex gap-3 mb-6">
|
|
||||||
<Button.Root
|
|
||||||
onclick={syncCreativeWorld}
|
|
||||||
class="bg-[#7aa2f7] hover:bg-[#7dcfff]"
|
|
||||||
>
|
|
||||||
Sync Creative World
|
|
||||||
</Button.Root>
|
|
||||||
<Button.Root
|
|
||||||
onclick={backupMainWorld}
|
|
||||||
class="bg-[#bb9af7] hover:bg-[#c0caf5]"
|
|
||||||
>
|
|
||||||
Backup Main World
|
|
||||||
</Button.Root>
|
|
||||||
</div>
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { createQuery } from "@tanstack/svelte-query";
|
|
||||||
import { fetchStats } from "./stats";
|
|
||||||
import { LoaderCircle } from "@lucide/svelte";
|
|
||||||
import {
|
|
||||||
formatDistance,
|
|
||||||
formatDistanceToNow,
|
|
||||||
formatDuration,
|
|
||||||
intervalToDuration,
|
|
||||||
} from "date-fns";
|
|
||||||
|
|
||||||
const query = createQuery(() => ({
|
|
||||||
queryKey: ["minecraft-server-stats"],
|
|
||||||
queryFn: () => fetchStats(),
|
|
||||||
refetchInterval: 10000,
|
|
||||||
staleTime: 5000,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const formatUptime = () => {
|
|
||||||
if (!query.data) {
|
|
||||||
return "--";
|
|
||||||
}
|
|
||||||
const started_at = query.data.uptime.started_at;
|
|
||||||
const duration = intervalToDuration({ start: started_at, end: new Date() });
|
|
||||||
$inspect(duration);
|
|
||||||
if (!duration.days && (duration.hours ?? 0) < 1) {
|
|
||||||
return formatDistanceToNow(new Date(query.data.uptime.started_at));
|
|
||||||
}
|
|
||||||
return formatDuration(duration, {
|
|
||||||
format: ["days", "hours", "minutes"],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#snippet statItem(label: string, value?: string | number)}
|
|
||||||
<div class="bg-zinc-700 rounded p-3">
|
|
||||||
<div class="text-sm">{label}</div>
|
|
||||||
<div class="text-xl text-white">{value}</div>
|
|
||||||
</div>
|
|
||||||
{/snippet}
|
|
||||||
|
|
||||||
<div class="border border-zinc-600 rounded-lg p-4">
|
|
||||||
<h3 class="text-lg font-medium mb-3">
|
|
||||||
Server Stats {#if query.isError}
|
|
||||||
<span class="ml-1 text-sm text-red-500"
|
|
||||||
>an error occured fetching server stats</span
|
|
||||||
>
|
|
||||||
{:else if query.isPending}
|
|
||||||
<LoaderCircle class="ml-1 w-4 h-4 inline-block animate-spin" />
|
|
||||||
{/if}
|
|
||||||
</h3>
|
|
||||||
<div class="grid grid-cols-2 gap-4 text-zinc-400">
|
|
||||||
{@render statItem("Players Online", query.data?.players_online ?? "--")}
|
|
||||||
{@render statItem("Server Status", query.data?.status ?? "--")}
|
|
||||||
{@render statItem("Uptime", formatUptime())}
|
|
||||||
{@render statItem("World Size", query.data?.world_size ?? "--")}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
type StatsResponse = {
|
|
||||||
status: string;
|
|
||||||
players_online: number;
|
|
||||||
max_players: number;
|
|
||||||
uptime: {
|
|
||||||
seconds: number;
|
|
||||||
started_at: string;
|
|
||||||
};
|
|
||||||
world_size: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const fetchStats = async () => {
|
|
||||||
const response = await fetch("/api/minecraft-server-stats");
|
|
||||||
return (await response.json()) as StatsResponse;
|
|
||||||
};
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import "./layout.css";
|
|
||||||
|
|
||||||
let { children } = $props();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{@render children()}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export const ssr = false;
|
|
||||||
export const prerender = false;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/svelte-query";
|
|
||||||
import Actions from "$lib/minecraft/Actions.svelte";
|
|
||||||
import Stats from "$lib/minecraft/Stats.svelte";
|
|
||||||
import { SvelteQueryDevtools } from "@tanstack/svelte-query-devtools";
|
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<QueryClientProvider client={queryClient}>
|
|
||||||
<main class="mt-8 flex justify-center">
|
|
||||||
<div class="w-full max-w-2xl px-4">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<h1 class="mb-8 text-2xl font-semibold">Management</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Minecraft Section -->
|
|
||||||
<section class="rounded-lg bg-zinc-800 p-6">
|
|
||||||
<h2 class="mb-4 text-xl">Minecraft</h2>
|
|
||||||
<Actions />
|
|
||||||
<Stats />
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<SvelteQueryDevtools />
|
|
||||||
</QueryClientProvider>
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
|
|
||||||
:root {
|
|
||||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
/* background-color: #242424; */
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* a { */
|
|
||||||
/* font-weight: 500; */
|
|
||||||
/* color: #646cff; */
|
|
||||||
/* text-decoration: inherit; */
|
|
||||||
/* } */
|
|
||||||
/* a:hover { */
|
|
||||||
/* color: #535bf2; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* body { */
|
|
||||||
/* margin: 0; */
|
|
||||||
/* display: flex; */
|
|
||||||
/* place-items: center; */
|
|
||||||
/* min-width: 320px; */
|
|
||||||
/* min-height: 100vh; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.2em;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #app { */
|
|
||||||
/* max-width: 1280px; */
|
|
||||||
/* margin: 0 auto; */
|
|
||||||
/* padding: 2rem; */
|
|
||||||
/* text-align: center; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s, background-color 0.2s;
|
|
||||||
color: #1a1b26
|
|
||||||
}
|
|
||||||
|
|
||||||
button:disabled {
|
|
||||||
cursor: default;
|
|
||||||
@apply bg-zinc-700
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
color: #213547;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #747bff;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,14 +0,0 @@
|
|||||||
import adapter from "@sveltejs/adapter-static";
|
|
||||||
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
|
||||||
|
|
||||||
/** @type {import("@sveltejs/kit").Config} */
|
|
||||||
export default {
|
|
||||||
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
|
||||||
// for more information about preprocessors
|
|
||||||
preprocess: vitePreprocess(),
|
|
||||||
kit: {
|
|
||||||
adapter: adapter({
|
|
||||||
fallback: "index.html",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "./.svelte-kit/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"rewriteRelativeImportExtensions": true,
|
|
||||||
"allowJs": true,
|
|
||||||
"checkJs": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"strict": true,
|
|
||||||
"moduleResolution": "bundler"
|
|
||||||
}
|
|
||||||
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
|
||||||
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
|
||||||
//
|
|
||||||
// To make changes to top-level options such as include and exclude, we recommend extending
|
|
||||||
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { defineConfig } from "vite";
|
|
||||||
import { sveltekit } from "@sveltejs/kit/vite";
|
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
|
||||||
|
|
||||||
// https://vite.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [sveltekit(), tailwindcss()],
|
|
||||||
server: {
|
|
||||||
proxy: {
|
|
||||||
"/api": {
|
|
||||||
target: "http://localhost:8080",
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -45,6 +45,13 @@ releases:
|
|||||||
values:
|
values:
|
||||||
- values/gitea.yaml
|
- values/gitea.yaml
|
||||||
|
|
||||||
|
- name: gitea-runners
|
||||||
|
namespace: git
|
||||||
|
chart: gitea-charts/actions
|
||||||
|
version: 0.0.2
|
||||||
|
values:
|
||||||
|
- values/gitea-runners.yaml
|
||||||
|
|
||||||
# Storage
|
# Storage
|
||||||
- name: longhorn
|
- name: longhorn
|
||||||
namespace: longhorn-system
|
namespace: longhorn-system
|
||||||
@@ -95,6 +102,13 @@ releases:
|
|||||||
values:
|
values:
|
||||||
- values/minecraft/creative.yaml
|
- values/minecraft/creative.yaml
|
||||||
|
|
||||||
|
- name: minecraft-old
|
||||||
|
namespace: minecraft
|
||||||
|
chart: minecraft-charts/minecraft
|
||||||
|
version: 5.0.0
|
||||||
|
values:
|
||||||
|
- values/minecraft/old.yaml
|
||||||
|
|
||||||
- name: home-assistant
|
- name: home-assistant
|
||||||
namespace: home
|
namespace: home
|
||||||
chart: home-assistant/home-assistant
|
chart: home-assistant/home-assistant
|
||||||
|
|||||||
5
nix/homelab/helm/values/gitea-runners.yaml
Normal file
5
nix/homelab/helm/values/gitea-runners.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
enabled: true
|
||||||
|
statefulset:
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: rufus
|
||||||
|
giteaRootURL: https://git.lucalise.ca
|
||||||
@@ -15,10 +15,11 @@ gitea:
|
|||||||
ROOT: /mnt/git-data/git/repositories
|
ROOT: /mnt/git-data/git/repositories
|
||||||
server:
|
server:
|
||||||
ROOT_URL: https://git.lucalise.ca
|
ROOT_URL: https://git.lucalise.ca
|
||||||
|
SSH_DOMAIN: git.lucalise.ca
|
||||||
database:
|
database:
|
||||||
DB_TYPE: sqlite3
|
DB_TYPE: sqlite3
|
||||||
session:
|
session:
|
||||||
PROVIDER: memory
|
PROVIDER: db
|
||||||
cache:
|
cache:
|
||||||
ADAPTER: memory
|
ADAPTER: memory
|
||||||
queue:
|
queue:
|
||||||
|
|||||||
@@ -3,23 +3,37 @@ resources:
|
|||||||
cpu: 1
|
cpu: 1
|
||||||
memory: 500Mi
|
memory: 500Mi
|
||||||
limits:
|
limits:
|
||||||
memory: 4Gi
|
memory: 5Gi
|
||||||
cpu: 2000m
|
cpu: 2000m
|
||||||
|
|
||||||
minecraftServer:
|
minecraftServer:
|
||||||
eula: "TRUE"
|
eula: "TRUE"
|
||||||
type: "PAPER"
|
type: "FABRIC"
|
||||||
version: "1.21.11"
|
version: "1.21.11"
|
||||||
difficulty: hard
|
difficulty: hard
|
||||||
motd: "A Minecraft Server."
|
motd: "A Minecraft Server."
|
||||||
gameMode: creative
|
gameMode: creative
|
||||||
memory: 4G
|
memory: 5G
|
||||||
rcon:
|
rcon:
|
||||||
enabled: true
|
enabled: true
|
||||||
withGeneratedPassword: false
|
withGeneratedPassword: false
|
||||||
port: 25575
|
port: 25575
|
||||||
existingSecret: rcon-credentials
|
existingSecret: rcon-credentials
|
||||||
secretKey: rcon-password
|
secretKey: rcon-password
|
||||||
|
modrinth:
|
||||||
|
projects:
|
||||||
|
- fabric-api
|
||||||
|
- tree-vein-miner
|
||||||
|
- lithium
|
||||||
|
- servux
|
||||||
|
- ferrite-core
|
||||||
|
- carpet
|
||||||
|
- elytra-trims
|
||||||
|
- fabric-language-kotlin
|
||||||
|
- c2me-fabric
|
||||||
|
- scalablelux
|
||||||
|
- axiom
|
||||||
|
|
||||||
|
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
kubernetes.io/hostname: kube
|
kubernetes.io/hostname: kube
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ resources:
|
|||||||
|
|
||||||
minecraftServer:
|
minecraftServer:
|
||||||
eula: "TRUE"
|
eula: "TRUE"
|
||||||
type: "PAPER"
|
type: "FABRIC"
|
||||||
version: "1.21.11"
|
version: "1.21.11"
|
||||||
difficulty: hard
|
difficulty: hard
|
||||||
motd: "A Minecraft Server."
|
motd: "A Minecraft Server."
|
||||||
@@ -21,7 +21,17 @@ minecraftServer:
|
|||||||
secretKey: rcon-password
|
secretKey: rcon-password
|
||||||
modrinth:
|
modrinth:
|
||||||
projects:
|
projects:
|
||||||
- treeminer
|
- fabric-api
|
||||||
|
- tree-vein-miner
|
||||||
|
- lithium
|
||||||
|
- servux
|
||||||
|
- ferrite-core
|
||||||
|
- carpet
|
||||||
|
- elytra-trims
|
||||||
|
- fabric-language-kotlin
|
||||||
|
- c2me-fabric
|
||||||
|
- scalablelux
|
||||||
|
- no-chat-reports
|
||||||
|
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
kubernetes.io/hostname: kube
|
kubernetes.io/hostname: kube
|
||||||
|
|||||||
29
nix/homelab/helm/values/minecraft/old.yaml
Normal file
29
nix/homelab/helm/values/minecraft/old.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
memory: 2Gi
|
||||||
|
cpu: 1
|
||||||
|
|
||||||
|
minecraftServer:
|
||||||
|
eula: "TRUE"
|
||||||
|
type: "VANILLA"
|
||||||
|
version: "1.7.10"
|
||||||
|
difficulty: hard
|
||||||
|
motd: "A Minecraft Server."
|
||||||
|
memory: 4G
|
||||||
|
rcon:
|
||||||
|
enabled: true
|
||||||
|
withGeneratedPassword: false
|
||||||
|
port: 25575
|
||||||
|
existingSecret: rcon-credentials
|
||||||
|
secretKey: rcon-password
|
||||||
|
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: rufus
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
dataDir:
|
||||||
|
enabled: true
|
||||||
|
Size: 2Gi
|
||||||
@@ -11,6 +11,9 @@ minecraftRouter:
|
|||||||
- externalHostname: "mc-rocket.privatedns.org"
|
- externalHostname: "mc-rocket.privatedns.org"
|
||||||
host: "minecraft-main"
|
host: "minecraft-main"
|
||||||
port: 25565
|
port: 25565
|
||||||
- externalHostname: "mc-rocket-creative.duckdns.org"
|
- externalHostname: "mc-rocket-creative.privatedns.org"
|
||||||
host: "minecraft-creative"
|
host: "minecraft-creative"
|
||||||
port: 25565
|
port: 25565
|
||||||
|
- externalHostname: "mc-rocket-old.privatedns.org"
|
||||||
|
host: "minecraft-old"
|
||||||
|
port: 25565
|
||||||
|
|||||||
33
nix/homelab/kustomize/backup-job-manual.yaml
Normal file
33
nix/homelab/kustomize/backup-job-manual.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: minecraft-backup-manual
|
||||||
|
namespace: minecraft
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
containers:
|
||||||
|
- name: backup
|
||||||
|
image: busybox
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -e
|
||||||
|
BACKUP_FILE=/backups/manual/minecraft-main-manual.tar.gz
|
||||||
|
echo "creating backup: ${BACKUP_FILE}"
|
||||||
|
tar -czf "${BACKUP_FILE}" -C /data .
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
- name: backups
|
||||||
|
mountPath: /backups
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: minecraft-main-datadir
|
||||||
|
- name: backups
|
||||||
|
nfs:
|
||||||
|
server: 192.168.27.2
|
||||||
|
path: /backup/minecraft
|
||||||
18
nix/homelab/kustomize/headscale-migrate.yaml
Normal file
18
nix/homelab/kustomize/headscale-migrate.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: headscale-migrate
|
||||||
|
namespace: networking
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
containers:
|
||||||
|
- name: migrate
|
||||||
|
image: nouchka/sqlite3
|
||||||
|
command: ["sleep", "infinity"]
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /var/lib/headscale
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: headscale-data
|
||||||
@@ -15,3 +15,6 @@ resources:
|
|||||||
- ./media/radarr.yaml
|
- ./media/radarr.yaml
|
||||||
- ./media/qbittorrent.yaml
|
- ./media/qbittorrent.yaml
|
||||||
- ./media/flaresolverr.yaml
|
- ./media/flaresolverr.yaml
|
||||||
|
|
||||||
|
- ./networking/headscale/config.yaml
|
||||||
|
- ./networking/headscale/headscale.yaml
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: sonarr
|
- name: sonarr
|
||||||
image: lscr.io/linuxserver/sonarr
|
image: lscr.io/linuxserver/sonarr:4.0.16
|
||||||
securityContext:
|
securityContext:
|
||||||
runAsUser: 0
|
runAsUser: 0
|
||||||
runAsGroup: 0
|
runAsGroup: 0
|
||||||
|
|||||||
50
nix/homelab/kustomize/networking/headscale/config.yaml
Normal file
50
nix/homelab/kustomize/networking/headscale/config.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: headscale-config
|
||||||
|
namespace: networking
|
||||||
|
data:
|
||||||
|
acl.json: |
|
||||||
|
{
|
||||||
|
"tagOwners": {
|
||||||
|
"tag:personal": ["lucalise@"],
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{"action": "accept", "src": ["tag:personal"], "dst": ["tag:personal:*"]},
|
||||||
|
{"action": "accept", "src": ["tag:personal"], "dst": ["autogroup:internet:*"]},
|
||||||
|
{"action": "accept", "src": ["tag:personal"], "dst": ["192.168.15.0/27:*", "192.168.27.0/24:*", "192.168.20.0/26:*"]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
config.yaml: |
|
||||||
|
server_url: https://mesh.lucalise.ca
|
||||||
|
listen_addr: 0.0.0.0:8080
|
||||||
|
metrics_listen_addr: 0.0.0.0:9090
|
||||||
|
|
||||||
|
noise:
|
||||||
|
private_key_path: /var/lib/headscale/noise_private.key
|
||||||
|
|
||||||
|
prefixes:
|
||||||
|
v4: 10.100.0.0/24
|
||||||
|
v6: fd7a:115c:a1e0::/48
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: sqlite3
|
||||||
|
sqlite:
|
||||||
|
path: /var/lib/headscale/db.sqlite
|
||||||
|
policy:
|
||||||
|
path: /etc/headscale/acl.json
|
||||||
|
|
||||||
|
dns:
|
||||||
|
override_local_dns: false
|
||||||
|
base_domain: m.net
|
||||||
|
|
||||||
|
derp:
|
||||||
|
server:
|
||||||
|
enabled: false
|
||||||
|
urls:
|
||||||
|
- https://controlplane.tailscale.com/derpmap/default
|
||||||
|
auto_update_enabled: true
|
||||||
|
update_frequency: 24h
|
||||||
|
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
88
nix/homelab/kustomize/networking/headscale/headscale.yaml
Normal file
88
nix/homelab/kustomize/networking/headscale/headscale.yaml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: headscale-data
|
||||||
|
namespace: networking
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: headscale
|
||||||
|
namespace: networking
|
||||||
|
labels:
|
||||||
|
app: headscale
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: headscale
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: headscale
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: headscale
|
||||||
|
image: docker.io/headscale/headscale
|
||||||
|
command: ["headscale", "serve"]
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
- containerPort: 9090
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 512m
|
||||||
|
memory: 1Gi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 30
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
volumeMounts:
|
||||||
|
- name: headscale-data
|
||||||
|
mountPath: /var/lib/headscale
|
||||||
|
- name: headscale-config
|
||||||
|
mountPath: /etc/headscale/config.yaml
|
||||||
|
subPath: config.yaml
|
||||||
|
- name: headscale-config
|
||||||
|
mountPath: /etc/headscale/acl.json
|
||||||
|
subPath: acl.json
|
||||||
|
volumes:
|
||||||
|
- name: headscale-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: headscale-data
|
||||||
|
- name: headscale-config
|
||||||
|
configMap:
|
||||||
|
name: headscale-config
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: headscale
|
||||||
|
namespace: networking
|
||||||
|
labels:
|
||||||
|
app: headscale
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: headscale
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
@@ -277,4 +277,20 @@ spec:
|
|||||||
extensionRef:
|
extensionRef:
|
||||||
group: traefik.io
|
group: traefik.io
|
||||||
kind: Middleware
|
kind: Middleware
|
||||||
name: private-networks
|
name: private-networks
|
||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: mesh
|
||||||
|
namespace: networking
|
||||||
|
spec:
|
||||||
|
parentRefs:
|
||||||
|
- name: traefik-gateway
|
||||||
|
namespace: kube-system
|
||||||
|
hostnames:
|
||||||
|
- mesh.lucalise.ca
|
||||||
|
rules:
|
||||||
|
- backendRefs:
|
||||||
|
- name: headscale
|
||||||
|
port: 8080
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
roboto
|
roboto
|
||||||
roboto-mono
|
roboto-mono
|
||||||
open-sans
|
open-sans
|
||||||
|
comic-relief
|
||||||
];
|
];
|
||||||
fonts.fontDir.enable = true;
|
fonts.fontDir.enable = true;
|
||||||
commonPackages = with pkgs; [
|
commonPackages = with pkgs; [
|
||||||
@@ -50,7 +51,6 @@
|
|||||||
gnumake
|
gnumake
|
||||||
watchman
|
watchman
|
||||||
bat
|
bat
|
||||||
rustup
|
|
||||||
emote
|
emote
|
||||||
pkg-config
|
pkg-config
|
||||||
openssl
|
openssl
|
||||||
@@ -78,6 +78,7 @@
|
|||||||
jless
|
jless
|
||||||
fd
|
fd
|
||||||
dig
|
dig
|
||||||
|
just
|
||||||
];
|
];
|
||||||
programs.nix-ld.enable = lib.mkDefault true;
|
programs.nix-ld.enable = lib.mkDefault true;
|
||||||
programs.zsh.enable = lib.mkDefault true;
|
programs.zsh.enable = lib.mkDefault true;
|
||||||
|
|||||||
@@ -21,5 +21,7 @@
|
|||||||
./dns.nix
|
./dns.nix
|
||||||
./mounts.nix
|
./mounts.nix
|
||||||
./nfs-mesh.nix
|
./nfs-mesh.nix
|
||||||
|
./rust.nix
|
||||||
|
# ./networking/wireguard-mesh.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
lib,
|
lib,
|
||||||
config,
|
config,
|
||||||
pkgs-before,
|
pkgs-before,
|
||||||
|
inputs,
|
||||||
|
meta,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
@@ -12,6 +14,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf config.desktop.enable {
|
config = lib.mkIf config.desktop.enable {
|
||||||
|
i18n.inputMethod = {
|
||||||
|
enable = true;
|
||||||
|
type = "fcitx5";
|
||||||
|
fcitx5.addons = with pkgs; [
|
||||||
|
fcitx5-mozc
|
||||||
|
fcitx5-gtk
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
vscode-fhs
|
vscode-fhs
|
||||||
pavucontrol
|
pavucontrol
|
||||||
@@ -50,6 +61,8 @@
|
|||||||
lm_sensors
|
lm_sensors
|
||||||
fanctl
|
fanctl
|
||||||
waypipe
|
waypipe
|
||||||
|
inputs.quickshell.packages.${meta.architecture}.default
|
||||||
|
alacritty
|
||||||
];
|
];
|
||||||
boot.kernelModules = [
|
boot.kernelModules = [
|
||||||
"iptables"
|
"iptables"
|
||||||
@@ -108,6 +121,14 @@
|
|||||||
};
|
};
|
||||||
xdg.configFile = {
|
xdg.configFile = {
|
||||||
"hypr/hyprlock.conf".source = ../../custom/hyprlock/hyprlock.conf;
|
"hypr/hyprlock.conf".source = ../../custom/hyprlock/hyprlock.conf;
|
||||||
|
"fcitx5/config".text = ''
|
||||||
|
[Hotkey]
|
||||||
|
TriggerKeys=
|
||||||
|
EnumerateWithTriggerKeys=True
|
||||||
|
EnumerateForwardKeys=
|
||||||
|
EnumerateBackwardKeys=
|
||||||
|
EnumerateSkipFirst=False
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
services.dunst = {
|
services.dunst = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -202,9 +223,15 @@
|
|||||||
"$mod, k, movefocus, u"
|
"$mod, k, movefocus, u"
|
||||||
"$mod, j, movefocus, d"
|
"$mod, j, movefocus, d"
|
||||||
"$mod, Space, togglesplit"
|
"$mod, Space, togglesplit"
|
||||||
|
"$mod SHIFT, h, movewindow, l"
|
||||||
|
"$mod SHIFT, l, movewindow, r"
|
||||||
"$mod SHIFT, v, exec, bash -c ~/dotfiles/scripts/copy.sh"
|
"$mod SHIFT, v, exec, bash -c ~/dotfiles/scripts/copy.sh"
|
||||||
"$mod SHIFT, s, exec, bash -c ~/dotfiles/scripts/screenshot.sh"
|
"$mod SHIFT, s, exec, bash -c ~/dotfiles/scripts/screenshot.sh"
|
||||||
"$mod, p, exec, bash -c ~/dotfiles/scripts/project.sh"
|
"$mod, p, exec, bash -c ~/dotfiles/scripts/project.sh"
|
||||||
|
"$mod SHIFT, k, exec, bash -c ~/dotfiles/scripts/layout.sh"
|
||||||
|
"$mod SHIFT, j, exec, fcitx5-remote -t"
|
||||||
|
"$mod CTRL, h, focusmonitor, l"
|
||||||
|
"$mod CTRL, l, focusmonitor, r"
|
||||||
|
|
||||||
"$mod, 0, workspace, 10"
|
"$mod, 0, workspace, 10"
|
||||||
"$mod SHIFT, 0, movetoworkspacesilent, 10"
|
"$mod SHIFT, 0, movetoworkspacesilent, 10"
|
||||||
@@ -235,14 +262,14 @@
|
|||||||
",XF86MonBrightnessDown, exec, bash -c 'brightnessctl s 5%- && perc=$(( \$(brightnessctl get) * 100 / \$(brightnessctl max) )) && notify-send \"Brightness\" -h int:value:\$perc -h string:synchronous:brightness -u low'"
|
",XF86MonBrightnessDown, exec, bash -c 'brightnessctl s 5%- && perc=$(( \$(brightnessctl get) * 100 / \$(brightnessctl max) )) && notify-send \"Brightness\" -h int:value:\$perc -h string:synchronous:brightness -u low'"
|
||||||
];
|
];
|
||||||
general = {
|
general = {
|
||||||
gaps_in = 0;
|
gaps_in = 5;
|
||||||
gaps_out = 10;
|
gaps_out = 10;
|
||||||
};
|
};
|
||||||
dwindle = {
|
dwindle = {
|
||||||
preserve_split = true;
|
preserve_split = true;
|
||||||
};
|
};
|
||||||
decoration = {
|
decoration = {
|
||||||
rounding = 0;
|
rounding = 10;
|
||||||
blur = {
|
blur = {
|
||||||
enabled = false;
|
enabled = false;
|
||||||
};
|
};
|
||||||
@@ -252,16 +279,21 @@
|
|||||||
"XCURSOR_SIZE,24"
|
"XCURSOR_SIZE,24"
|
||||||
"LIBVA_DRIVER_NAME,nvidia"
|
"LIBVA_DRIVER_NAME,nvidia"
|
||||||
"__GLX_VENDOR_LIBRARY_NAME,nvidia"
|
"__GLX_VENDOR_LIBRARY_NAME,nvidia"
|
||||||
|
# "GTK_IM_MODULE,fcitx"
|
||||||
|
# "QT_IM_MODULE,fcitx"
|
||||||
|
"XMODIFIERS,@im=fcitx"
|
||||||
];
|
];
|
||||||
exec-once = [
|
exec-once = [
|
||||||
"status-bar"
|
# "status-bar"
|
||||||
|
"qs"
|
||||||
"wl-clip-persist --clipboard regular"
|
"wl-clip-persist --clipboard regular"
|
||||||
|
"fcitx5 -d"
|
||||||
];
|
];
|
||||||
monitor = [
|
monitor = [
|
||||||
"eDP-1, 1920x1080, 0x0, 1"
|
"eDP-1, 1920x1080, 0x0, 1"
|
||||||
];
|
];
|
||||||
input = {
|
input = {
|
||||||
kb_layout = "us";
|
kb_layout = "us,jp";
|
||||||
touchpad = {
|
touchpad = {
|
||||||
natural_scroll = true;
|
natural_scroll = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
];
|
];
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
[Resolve]
|
[Resolve]
|
||||||
DNS=192.168.27.13:53
|
DNS=192.168.27.13:53 1.1.1.1 1.0.0.1
|
||||||
ResolveUnicastSingleLabel=yes
|
ResolveUnicastSingleLabel=yes
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|||||||
90
nix/modules/networking/wireguard-mesh.nix
Normal file
90
nix/modules/networking/wireguard-mesh.nix
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
meshHosts = {
|
||||||
|
kumatani = {
|
||||||
|
address = "kumatani";
|
||||||
|
publicKey = "pKkl30tba29FG86wuaC0KrpSHMr1tSOujikHFbx75BM=";
|
||||||
|
isRouter = false;
|
||||||
|
ip = "10.100.0.1";
|
||||||
|
};
|
||||||
|
usahara = {
|
||||||
|
address = "usahara";
|
||||||
|
publicKey = "4v7GyAIsKfwWjLMVB4eoosJDvLkIDHW0KsEYoQqSnh4=";
|
||||||
|
isRouter = false;
|
||||||
|
ip = "10.100.0.2";
|
||||||
|
};
|
||||||
|
tux = {
|
||||||
|
address = "tux";
|
||||||
|
publicKey = "Z17ci3Flk1eDAhJ8QZSUgtmlw6BVu4XqvpqLKLWTYWw=";
|
||||||
|
isRouter = false;
|
||||||
|
ip = "10.100.0.3";
|
||||||
|
};
|
||||||
|
oakbay-pfsense = {
|
||||||
|
endpoint = "oakbay.lucalise.ca:51822";
|
||||||
|
publicKey = "xOTPZBIC9m1BkkiLCOUTty3b7/NOvslteVQHzEFxqWQ=";
|
||||||
|
isRouter = true;
|
||||||
|
ip = "10.100.0.250";
|
||||||
|
routes = [
|
||||||
|
"10.100.0.0/24"
|
||||||
|
"192.168.15.0/27"
|
||||||
|
"192.168.20.0/26"
|
||||||
|
"192.168.27.0/24"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
pearce-udm = {
|
||||||
|
endpoint = "pearce.kisame.ca:51823";
|
||||||
|
publicKey = "hDb2DzI+isaqXLdxwAF1hc5Nid8TK/M1SQ+zDpf9QxY=";
|
||||||
|
isRouter = true;
|
||||||
|
ip = "10.100.0.251";
|
||||||
|
routes = [
|
||||||
|
"192.168.18.0/27"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
getEndpoint =
|
||||||
|
name: host:
|
||||||
|
if host.isRouter or false then "${host.endpoint}" else "${host.address}:${toString 51820}";
|
||||||
|
|
||||||
|
mkPeer = name: host: {
|
||||||
|
publicKey = host.publicKey;
|
||||||
|
allowedIPs = [ "${host.ip}/32" ] ++ (host.routes or [ ]);
|
||||||
|
endpoint = getEndpoint name host;
|
||||||
|
persistentKeepalive = 25;
|
||||||
|
dynamicEndpointRefreshSeconds = 300;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkPeersFor =
|
||||||
|
selfName:
|
||||||
|
lib.mapAttrsToList mkPeer (
|
||||||
|
lib.filterAttrs (name: host: name != selfName && (host.isRouter or false)) meshHosts
|
||||||
|
);
|
||||||
|
|
||||||
|
selfConfig = meshHosts.${config.networking.hostName} or null;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = lib.mkIf (selfConfig != null) {
|
||||||
|
networking.wireguard.interfaces = {
|
||||||
|
wg0 = {
|
||||||
|
privateKeyFile = "/etc/wireguard/private.key";
|
||||||
|
ips = [ "${selfConfig.ip}/32" ];
|
||||||
|
listenPort = 51820;
|
||||||
|
peers = mkPeersFor config.networking.hostName;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall = {
|
||||||
|
allowedUDPPorts = [ 51820 ];
|
||||||
|
trustedInterfaces = [ "wg0" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /etc/wireguard 0700 root root -"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
44
nix/modules/rust.nix
Normal file
44
nix/modules/rust.nix
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
options.rust = {
|
||||||
|
enable = lib.mkEnableOption "enable rust" // {
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.rust.enable {
|
||||||
|
nixpkgs.overlays = [ inputs.fenix.overlays.default ];
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
(pkgs.fenix.stable.withComponents [
|
||||||
|
"cargo"
|
||||||
|
"clippy"
|
||||||
|
"rust-src"
|
||||||
|
"rustc"
|
||||||
|
"rustfmt"
|
||||||
|
])
|
||||||
|
openssl
|
||||||
|
pkgconf
|
||||||
|
];
|
||||||
|
environment.variables = {
|
||||||
|
PKG_CONFIG_PATH =
|
||||||
|
with pkgs;
|
||||||
|
lib.makeSearchPath "/lib/pkgconfig" [
|
||||||
|
openssl.dev
|
||||||
|
];
|
||||||
|
LD_LIBRARY_PATH = "/run/current-system/sw/share/nix-ld/lib";
|
||||||
|
};
|
||||||
|
programs.nix-ld.libraries = with pkgs; [
|
||||||
|
openssl
|
||||||
|
zlib
|
||||||
|
brotli
|
||||||
|
unixODBC
|
||||||
|
glib
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
oh-my-posh = import ./omp.nix;
|
oh-my-posh = import ./omp.nix;
|
||||||
eza = import ./eza.nix;
|
eza = import ./eza.nix;
|
||||||
mise = import ./mise.nix;
|
mise = import ./mise.nix;
|
||||||
|
bacon.enable = true;
|
||||||
|
jujutsu = import ./jj.nix;
|
||||||
};
|
};
|
||||||
xdg.mimeApps = import ./mime.nix;
|
xdg.mimeApps = import ./mime.nix;
|
||||||
|
|
||||||
@@ -23,27 +25,6 @@
|
|||||||
nodejs_22
|
nodejs_22
|
||||||
pnpm
|
pnpm
|
||||||
];
|
];
|
||||||
systemd.user.services.ssh-add-keys = {
|
|
||||||
Unit = {
|
|
||||||
Description = "Load SSH keys from YubiKey";
|
|
||||||
After = [ "ssh-agent.service" ];
|
|
||||||
Requires = [ "ssh-agent.service" ];
|
|
||||||
};
|
|
||||||
Service = {
|
|
||||||
Type = "oneshot";
|
|
||||||
Environment = [
|
|
||||||
"SSH_AUTH_SOCK=%t/ssh-agent"
|
|
||||||
"SSH_ASKPASS=${pkgs.lxqt.lxqt-openssh-askpass}/bin/lxqt-openssh-askpass"
|
|
||||||
"SSH_ASKPASS_REQUIRE=prefer"
|
|
||||||
"DISPLAY=:0"
|
|
||||||
];
|
|
||||||
ExecStart = "${pkgs.openssh}/bin/ssh-add -K";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
};
|
|
||||||
Install = {
|
|
||||||
WantedBy = [ "default.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
home.stateVersion = "24.11";
|
home.stateVersion = "24.11";
|
||||||
|
|
||||||
|
|||||||
14
nix/users/luca/jj.nix
Normal file
14
nix/users/luca/jj.nix
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
user = {
|
||||||
|
email = "luca_lise@icloud.com";
|
||||||
|
name = "lucalise";
|
||||||
|
};
|
||||||
|
signing = {
|
||||||
|
behavior = "own";
|
||||||
|
backend = "ssh";
|
||||||
|
key = "~/.ssh/id_ed25519.pub";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ in
|
|||||||
"rust"
|
"rust"
|
||||||
"kubectl"
|
"kubectl"
|
||||||
"helm"
|
"helm"
|
||||||
|
"jj"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
plugins = [
|
plugins = [
|
||||||
|
|||||||
18
scripts/layout.sh
Executable file
18
scripts/layout.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Rofi-based keyboard layout switcher for Hyprland
|
||||||
|
|
||||||
|
layouts="🇨🇦 Canadian (CA)
|
||||||
|
🇯🇵 Japanese (JP)"
|
||||||
|
|
||||||
|
selected=$(echo "$layouts" | rofi -dmenu -p "Layout")
|
||||||
|
|
||||||
|
case "$selected" in
|
||||||
|
*"Canadian"*)
|
||||||
|
hyprctl switchxkblayout all 0
|
||||||
|
notify-send -h string:synchronous:keyboard "Keyboard" "🇨🇦 Canadian (CA)"
|
||||||
|
;;
|
||||||
|
*"Japanese"*)
|
||||||
|
hyprctl switchxkblayout all 1
|
||||||
|
notify-send -h string:synchronous:keyboard "Keyboard" "🇯🇵 Japanese (JP)"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user