Compare commits
23 Commits
58ead2bb23
...
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
|
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 }
|
||||
urlencoding = "2"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
".",
|
||||
"cli"
|
||||
]
|
||||
|
||||
[features]
|
||||
default = ["file-config"]
|
||||
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",
|
||||
port = 80,
|
||||
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/gitea.yaml
|
||||
|
||||
- name: gitea-runners
|
||||
namespace: git
|
||||
chart: gitea-charts/actions
|
||||
version: 0.0.2
|
||||
values:
|
||||
- values/gitea-runners.yaml
|
||||
|
||||
# Storage
|
||||
- name: longhorn
|
||||
namespace: longhorn-system
|
||||
@@ -95,6 +102,13 @@ releases:
|
||||
values:
|
||||
- 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
|
||||
namespace: home
|
||||
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
|
||||
@@ -3,23 +3,37 @@ resources:
|
||||
cpu: 1
|
||||
memory: 500Mi
|
||||
limits:
|
||||
memory: 4Gi
|
||||
memory: 5Gi
|
||||
cpu: 2000m
|
||||
|
||||
minecraftServer:
|
||||
eula: "TRUE"
|
||||
type: "PAPER"
|
||||
type: "FABRIC"
|
||||
version: "1.21.11"
|
||||
difficulty: hard
|
||||
motd: "A Minecraft Server."
|
||||
gameMode: creative
|
||||
memory: 4G
|
||||
memory: 5G
|
||||
rcon:
|
||||
enabled: true
|
||||
withGeneratedPassword: false
|
||||
port: 25575
|
||||
existingSecret: rcon-credentials
|
||||
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:
|
||||
kubernetes.io/hostname: kube
|
||||
|
||||
@@ -8,7 +8,7 @@ resources:
|
||||
|
||||
minecraftServer:
|
||||
eula: "TRUE"
|
||||
type: "PAPER"
|
||||
type: "FABRIC"
|
||||
version: "1.21.11"
|
||||
difficulty: hard
|
||||
motd: "A Minecraft Server."
|
||||
@@ -21,8 +21,17 @@ minecraftServer:
|
||||
secretKey: rcon-password
|
||||
modrinth:
|
||||
projects:
|
||||
- treeminer
|
||||
- fast-leaf-decay
|
||||
- fabric-api
|
||||
- tree-vein-miner
|
||||
- lithium
|
||||
- servux
|
||||
- ferrite-core
|
||||
- carpet
|
||||
- elytra-trims
|
||||
- fabric-language-kotlin
|
||||
- c2me-fabric
|
||||
- scalablelux
|
||||
- no-chat-reports
|
||||
|
||||
nodeSelector:
|
||||
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"
|
||||
host: "minecraft-main"
|
||||
port: 25565
|
||||
- externalHostname: "mc-rocket-creative.duckdns.org"
|
||||
- externalHostname: "mc-rocket-creative.privatedns.org"
|
||||
host: "minecraft-creative"
|
||||
port: 25565
|
||||
- externalHostname: "mc-rocket-old.privatedns.org"
|
||||
host: "minecraft-old"
|
||||
port: 25565
|
||||
|
||||
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/qbittorrent.yaml
|
||||
- ./media/flaresolverr.yaml
|
||||
|
||||
- ./networking/headscale/config.yaml
|
||||
- ./networking/headscale/headscale.yaml
|
||||
|
||||
@@ -34,7 +34,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: sonarr
|
||||
image: lscr.io/linuxserver/sonarr
|
||||
image: lscr.io/linuxserver/sonarr:4.0.16
|
||||
securityContext:
|
||||
runAsUser: 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:
|
||||
group: traefik.io
|
||||
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
|
||||
@@ -78,6 +78,7 @@
|
||||
jless
|
||||
fd
|
||||
dig
|
||||
just
|
||||
];
|
||||
programs.nix-ld.enable = lib.mkDefault true;
|
||||
programs.zsh.enable = lib.mkDefault true;
|
||||
|
||||
@@ -22,5 +22,6 @@
|
||||
./mounts.nix
|
||||
./nfs-mesh.nix
|
||||
./rust.nix
|
||||
# ./networking/wireguard-mesh.nix
|
||||
];
|
||||
}
|
||||
|
||||
@@ -14,6 +14,15 @@
|
||||
};
|
||||
|
||||
config = lib.mkIf config.desktop.enable {
|
||||
i18n.inputMethod = {
|
||||
enable = true;
|
||||
type = "fcitx5";
|
||||
fcitx5.addons = with pkgs; [
|
||||
fcitx5-mozc
|
||||
fcitx5-gtk
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vscode-fhs
|
||||
pavucontrol
|
||||
@@ -53,6 +62,7 @@
|
||||
fanctl
|
||||
waypipe
|
||||
inputs.quickshell.packages.${meta.architecture}.default
|
||||
alacritty
|
||||
];
|
||||
boot.kernelModules = [
|
||||
"iptables"
|
||||
@@ -111,6 +121,14 @@
|
||||
};
|
||||
xdg.configFile = {
|
||||
"hypr/hyprlock.conf".source = ../../custom/hyprlock/hyprlock.conf;
|
||||
"fcitx5/config".text = ''
|
||||
[Hotkey]
|
||||
TriggerKeys=
|
||||
EnumerateWithTriggerKeys=True
|
||||
EnumerateForwardKeys=
|
||||
EnumerateBackwardKeys=
|
||||
EnumerateSkipFirst=False
|
||||
'';
|
||||
};
|
||||
services.dunst = {
|
||||
enable = true;
|
||||
@@ -210,6 +228,10 @@
|
||||
"$mod SHIFT, v, exec, bash -c ~/dotfiles/scripts/copy.sh"
|
||||
"$mod SHIFT, s, exec, bash -c ~/dotfiles/scripts/screenshot.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 SHIFT, 0, movetoworkspacesilent, 10"
|
||||
@@ -257,17 +279,21 @@
|
||||
"XCURSOR_SIZE,24"
|
||||
"LIBVA_DRIVER_NAME,nvidia"
|
||||
"__GLX_VENDOR_LIBRARY_NAME,nvidia"
|
||||
# "GTK_IM_MODULE,fcitx"
|
||||
# "QT_IM_MODULE,fcitx"
|
||||
"XMODIFIERS,@im=fcitx"
|
||||
];
|
||||
exec-once = [
|
||||
# "status-bar"
|
||||
"qs"
|
||||
"wl-clip-persist --clipboard regular"
|
||||
"fcitx5 -d"
|
||||
];
|
||||
monitor = [
|
||||
"eDP-1, 1920x1080, 0x0, 1"
|
||||
];
|
||||
input = {
|
||||
kb_layout = "us";
|
||||
kb_layout = "us,jp";
|
||||
touchpad = {
|
||||
natural_scroll = true;
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
];
|
||||
extraConfig = ''
|
||||
[Resolve]
|
||||
DNS=192.168.27.13:53
|
||||
DNS=192.168.27.13:53 1.1.1.1 1.0.0.1
|
||||
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 -"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
oh-my-posh = import ./omp.nix;
|
||||
eza = import ./eza.nix;
|
||||
mise = import ./mise.nix;
|
||||
bacon.enable = true;
|
||||
jujutsu = import ./jj.nix;
|
||||
};
|
||||
xdg.mimeApps = import ./mime.nix;
|
||||
|
||||
@@ -23,27 +25,6 @@
|
||||
nodejs_22
|
||||
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";
|
||||
|
||||
|
||||
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"
|
||||
"kubectl"
|
||||
"helm"
|
||||
"jj"
|
||||
];
|
||||
};
|
||||
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