Compare commits

..

2 Commits

Author SHA1 Message Date
Brian McGee
985f66dac8 feat(ui): lazy load routes 2025-05-22 16:05:18 +01:00
Brian McGee
0a75575e08 feat(ui): move route definitions to routes folder 2025-05-22 15:33:39 +01:00
125 changed files with 568 additions and 8693 deletions

View File

@@ -1,6 +1,6 @@
{ fetchgit }:
fetchgit {
url = "https://git.clan.lol/clan/clan-core.git";
rev = "4b44892b476b32b1ca7d2f637da41562b8ed5456";
sha256 = "15k7dp3m9dcvx75sm900xp70vss2pnx0ywjnpmqyqlmwpvzn663p";
rev = "843e1b24be6ff9a7015e67b3291216c08f628d3e";
sha256 = "1bfm3n9r9k8prbwsh0yzp421y4ahblv407gqihwvcpiqsx6s3b9b";
}

View File

@@ -0,0 +1,7 @@
---
description = "Configures Wifi networks to join"
features = [ "inventory", "experimental", "deprecated" ]
categories = [ "Network", "System" ]
---
## Experimental wifi module

View File

@@ -0,0 +1,5 @@
{
imports = [
./roles/default.nix
];
}

View File

@@ -0,0 +1,110 @@
{
lib,
config,
pkgs,
...
}:
let
cfg = config.clan.wifi;
inherit (lib)
concatMapAttrsStringSep
flip
mapAttrs
;
password_path =
network_name: config.clan.core.vars.generators."iwd.${network_name}".files.password.path;
ssid_path = network_name: config.clan.core.vars.generators."iwd.${network_name}".files.ssid.path;
secret_generator = name: value: {
name = "iwd.${name}";
value = {
prompts.ssid.type = "line";
prompts.ssid.persist = true;
prompts.password.type = "hidden";
prompts.password.persist = true;
share = true;
};
};
in
{
options.clan.wifi = {
networks = lib.mkOption {
visible = false;
type = lib.types.attrsOf (
lib.types.submodule (
{ ... }:
{
options = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Enable this wifi network";
};
autoConnect = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Automatically try to join this wifi network";
};
};
}
)
);
default = { };
description = "Wifi networks to predefine";
};
};
config = lib.mkIf (cfg.networks != { }) {
clan.core.vars.generators = lib.mapAttrs' secret_generator cfg.networks;
networking.networkmanager.enable = true;
networking.networkmanager.ensureProfiles.environmentFiles = [
"/run/secrets/NetworkManager/wifi-secrets"
];
networking.networkmanager.ensureProfiles.profiles = flip mapAttrs cfg.networks (
name: _network: {
connection.id = "$ssid_${name}";
connection.type = "wifi";
wifi.mode = "infrastructure";
wifi.ssid = "$ssid_${name}";
wifi-security.psk = "$pw_${name}";
wifi-security.key-mgmt = "wpa-psk";
}
);
# service to generate the environment file containing all secrets, as
# expected by the nixos NetworkManager-ensure-profile service
systemd.services.NetworkManager-setup-secrets = {
description = "Generate wifi secrets for NetworkManager";
requiredBy = [ "NetworkManager-ensure-profiles.service" ];
partOf = [ "NetworkManager-ensure-profiles.service" ];
before = [ "NetworkManager-ensure-profiles.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "wifi-secrets" ''
set -euo pipefail
env_file=/run/secrets/NetworkManager/wifi-secrets
mkdir -p $(dirname "$env_file")
: > "$env_file"
# Generate the secrets file
echo "Generating wifi secrets file: $env_file"
${flip (concatMapAttrsStringSep "\n") cfg.networks (
name: _network: ''
echo "ssid_${name}=\"$(cat "${ssid_path name}")\"" >> /run/secrets/NetworkManager/wifi-secrets
echo "pw_${name}=\"$(cat "${password_path name}")\"" >> /run/secrets/NetworkManager/wifi-secrets
''
)}
'';
};
};
};
}

View File

@@ -1,12 +1,5 @@
{ packages }:
{ lib, ... }:
let
inherit (lib)
concatMapAttrsStringSep
flip
mapAttrs
;
in
{
_class = "clan.service";
manifest.name = "wifi";
@@ -37,19 +30,17 @@ in
default = { };
description = "Wifi networks to predefine";
};
};
};
perInstance =
{ settings, ... }:
{
nixosModule =
{ pkgs, config, ... }:
{ config, pkgs, ... }:
let
password_path =
secret_path =
network_name: config.clan.core.vars.generators."iwd.${network_name}".files.password.path;
ssid_path = network_name: config.clan.core.vars.generators."iwd.${network_name}".files.ssid.path;
secret_generator = name: value: {
name = "iwd.${name}";
value = {
@@ -61,55 +52,59 @@ in
};
};
in
lib.mkIf (settings.networks != { }) {
{
clan.core.vars.generators = lib.mapAttrs' secret_generator settings.networks;
networking.networkmanager.enable = true;
systemd.services.iwd.partOf = [ "nixos-activation.service" ];
networking.networkmanager.ensureProfiles.environmentFiles = [
"/run/secrets/NetworkManager/wifi-secrets"
];
/*
script that generates iwd config files inside /var/lib/iwd/clan and symlinks
them to /var/lib/iwd.
*/
systemd.services.iwd.serviceConfig.ExecStartPre = pkgs.writeShellScript "clan-iwd-setup" ''
set -e
networking.networkmanager.ensureProfiles.profiles = flip mapAttrs settings.networks (
name: _network: {
connection.id = "$ssid_${name}";
connection.type = "wifi";
wifi.mode = "infrastructure";
wifi.ssid = "$ssid_${name}";
wifi-security.psk = "$pw_${name}";
wifi-security.key-mgmt = "wpa-psk";
}
);
rm -rf /var/lib/iwd/clan
mkdir -p /var/lib/iwd/clan
# service to generate the environment file containing all secrets, as
# expected by the nixos NetworkManager-ensure-profile service
systemd.services.NetworkManager-setup-secrets = {
description = "Generate wifi secrets for NetworkManager";
requiredBy = [ "NetworkManager-ensure-profiles.service" ];
partOf = [ "NetworkManager-ensure-profiles.service" ];
before = [ "NetworkManager-ensure-profiles.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "wifi-secrets" ''
set -euo pipefail
# remove all existing symlinks in /var/lib/iwd
${pkgs.findutils}/bin/find /var/lib/iwd -type l -exec rm {} \;
env_file=/run/secrets/NetworkManager/wifi-secrets
mkdir -p $(dirname "$env_file")
: > "$env_file"
${toString (
lib.mapAttrsToList (name: network: ''
passwd=$(cat "${secret_path name}")
ssid=$(cat "${ssid_path name}")
echo "
[Settings]
autoConnect=${if network.autoConnect then "true" else "false"}
[Security]
Passphrase=$passwd
" > "/var/lib/iwd/clan/$ssid.psk"
'') settings.networks
)}
# Generate the secrets file
echo "Generating wifi secrets file: $env_file"
${flip (concatMapAttrsStringSep "\n") settings.networks (
name: _network: ''
echo "ssid_${name}=\"$(cat "${ssid_path name}")\"" >> /run/secrets/NetworkManager/wifi-secrets
echo "pw_${name}=\"$(cat "${password_path name}")\"" >> /run/secrets/NetworkManager/wifi-secrets
''
)}
'';
# link all files in /var/lib/iwd/clan to /var/lib/iwd
${pkgs.findutils}/bin/find /var/lib/iwd/clan -type f -exec ln -s {} /var/lib/iwd \;
'';
# disable wpa supplicant
networking.wireless.enable = false;
# Set the network manager backend to iwd
networking.networkmanager.wifi.backend = "iwd";
# Use iwd instead of wpa_supplicant. It has a user friendly CLI
networking.wireless.iwd = {
enable = true;
settings = {
Network = {
EnableIPv6 = true;
RoutePriorityOffset = 300;
};
Settings.autoConnect = true;
};
};
};
};
};
}

View File

@@ -15,8 +15,8 @@ clanLib.test.makeTestClan {
clan = {
directory = ./.;
modules."@clan/wifi" = module;
inventory = {
modules."@clan/wifi" = module;
machines.test = { };
@@ -34,8 +34,8 @@ clanLib.test.makeTestClan {
testScript = ''
start_all()
test.wait_for_unit("NetworkManager.service")
psk = test.succeed("cat /run/NetworkManager/system-connections/one.nmconnection")
test.wait_for_unit("iwd.service")
psk = test.succeed("cat /var/lib/iwd/ssid-one.psk")
assert "password-eins" in psk, "Password is incorrect"
'';
}

View File

@@ -87,6 +87,7 @@ nav:
- reference/clanServices/wifi.md
- Clan Modules:
- Overview: reference/clanModules/index.md
- Frontmatter Format: reference/clanModules/frontmatter/index.md
- reference/clanModules/frontmatter/index.md
# TODO: display the docs of the clan.service modules
- reference/clanModules/admin.md

View File

@@ -18,7 +18,7 @@ This section will walk you through the following steps:
1. declare a `generator` in the machine's nixos configuration
2. inspect the status via the Clan CLI
3. generate the vars
4. observe the changes
4. observer the changes
5. update the machine
6. share the root password between machines
7. change the password

32
flake.lock generated
View File

@@ -16,11 +16,11 @@
]
},
"locked": {
"lastModified": 1748244631,
"narHash": "sha256-fLJu837n0aP6ky+3qYUCaQN2ZESOh2Tvho8RA73DLZw=",
"rev": "f52e3eef263617f5b15a4486720e98a7aada8de3",
"lastModified": 1747612895,
"narHash": "sha256-6niXZ5gTe456bq6udlP6QWe7MJgNybqCHqMzhkFf2gA=",
"rev": "54989ab33b3b5ff5e21e89ce11f0b72b3979ffd6",
"type": "tarball",
"url": "https://git.clan.lol/api/v1/repos/clan/data-mesher/archive/f52e3eef263617f5b15a4486720e98a7aada8de3.tar.gz"
"url": "https://git.clan.lol/api/v1/repos/clan/data-mesher/archive/54989ab33b3b5ff5e21e89ce11f0b72b3979ffd6.tar.gz"
},
"original": {
"type": "tarball",
@@ -34,11 +34,11 @@
]
},
"locked": {
"lastModified": 1748225455,
"narHash": "sha256-AzlJCKaM4wbEyEpV3I/PUq5mHnib2ryEy32c+qfj6xk=",
"lastModified": 1747742835,
"narHash": "sha256-kYL4GCwwznsypvsnA20oyvW8zB/Dvn6K5G/tgMjVMT4=",
"owner": "nix-community",
"repo": "disko",
"rev": "a894f2811e1ee8d10c50560551e50d6ab3c392ba",
"rev": "df522e787fdffc4f32ed3e1fca9ed0968a384d62",
"type": "github"
},
"original": {
@@ -74,11 +74,11 @@
]
},
"locked": {
"lastModified": 1748149228,
"narHash": "sha256-mmonYFesFo42UUS49Hd0bcbVJRWX/aHBCDYUkkvylf4=",
"lastModified": 1747752313,
"narHash": "sha256-Z5OnPIZ3/ijo5xLCOpWoVbUE5JNnGxSHGhnJ3u9f2GE=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "a9939228f661df370c4094fe85f683e45d761dbe",
"rev": "9ed53ae9abb5b125e453f37e475da5b8c368e676",
"type": "github"
},
"original": {
@@ -118,10 +118,10 @@
"nixpkgs": {
"locked": {
"lastModified": 315532800,
"narHash": "sha256-A6ddIFRZ6y1IQQY0Gu868W9le0wuJfI1qYcVpq++f+I=",
"rev": "bdac72d387dca7f836f6ef1fe547755fb0e9df61",
"narHash": "sha256-5KmFi32WR68m92jX0eKBQ7HPDoL1ufYvzRjGg+dgWNs=",
"rev": "359c442b7d1f6229c1dc978116d32d6c07fe8440",
"type": "tarball",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre805949.bdac72d387dc/nixexprs.tar.xz"
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre803292.359c442b7d1f/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
@@ -184,11 +184,11 @@
]
},
"locked": {
"lastModified": 1748243702,
"narHash": "sha256-9YzfeN8CB6SzNPyPm2XjRRqSixDopTapaRsnTpXUEY8=",
"lastModified": 1747469671,
"narHash": "sha256-bo1ptiFoNqm6m1B2iAhJmWCBmqveLVvxom6xKmtuzjg=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "1f3f7b784643d488ba4bf315638b2b0a4c5fb007",
"rev": "ab0378b61b0d85e73a8ab05d5c6029b5bd58c9fb",
"type": "github"
},
"original": {

View File

@@ -15,16 +15,10 @@ let
url = "https://github.com/Omnibus-Type/Archivo/raw/b5d63988ce19d044d3e10362de730af00526b672/fonts/webfonts/ArchivoSemiCondensed-SemiBold.woff2";
hash = "sha256-fOE+b+UeTRoj+sDdUWR1pPCZVn0ABy6FEDDmXrOA4LY=";
};
vt323 = fetchurl {
url = "https://github.com/google/fonts/raw/c781e48f571fe26740a9814c0461064628cbd175/ofl/vt323/VT323-Regular.ttf";
hash = "sha256-z03nUa2njOrAM9vhamh3QpOZlbd7wqBSrheklXlYWU0=";
};
in
runCommand "" { } ''
mkdir -p $out
cp ${archivoRegular} $out/ArchivoSemiCondensed-Regular.woff2
cp ${archivoMedium} $out/ArchivoSemiCondensed-Medium.woff2
cp ${archivoSemiBold} $out/ArchivoSemiCondensed-SemiBold.woff2
cp ${vt323} $out/VT323-Regular.ttf
''

View File

@@ -1,32 +0,0 @@
import { createRequire } from "module";
import { dirname, join } from "path";
import { mergeConfig } from "vite";
import type { StorybookConfig } from "@kachurun/storybook-solid-vite";
const require = createRequire(import.meta.url);
const getAbsolutePath = (pkg: string) =>
dirname(require.resolve(join(pkg, "package.json")));
const config: StorybookConfig = {
stories: ["../src/components/**/*.mdx", "../src/components/**/*.stories.tsx"],
addons: [
getAbsolutePath("@storybook/addon-links"),
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@chromatic-com/storybook"),
getAbsolutePath("@storybook/addon-interactions"),
],
framework: {
name: "@kachurun/storybook-solid-vite",
options: {},
},
async viteFinal(config) {
return mergeConfig(config, {
define: { "process.env": {} },
});
},
docs: {
autodocs: "tag",
},
};
export default config;

View File

@@ -1,27 +0,0 @@
import type { Preview } from "@kachurun/storybook-solid";
import "../src/index.css";
export const preview: Preview = {
tags: ["autodocs"],
parameters: {
docs: { toc: true },
backgrounds: {
values: [
{ name: "Dark", value: "#333" },
{ name: "Light", value: "#F7F9F2" },
],
default: "Light",
},
// automatically create action args for all props that start with "on"
actions: { argTypesRegex: "^on.*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
},
};
export default preview;

View File

@@ -31,12 +31,6 @@ Solid in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br> Your app is
ready to be deployed!
### `npm run storybook`
Starts an instance of [storybook](https://storybook.js.org/).
For more info on how to write stories, please [see here](https://storybook.js.org/docs).
## Deployment
You can deploy the `dist` folder to any static host provider (netlify, surge,

File diff suppressed because it is too large Load Diff

View File

@@ -10,22 +10,12 @@
"convert-html": "node gtk.webview.js",
"serve": "vite preview",
"check": "tsc --noEmit --skipLibCheck && eslint ./src",
"test": "vitest run --typecheck",
"storybook": "storybook dev -p 6006"
"test": "vitest run --typecheck"
},
"license": "MIT",
"devDependencies": {
"@babel/plugin-syntax-import-attributes": "^7.27.1",
"@chromatic-com/storybook": "^3.2.6",
"@eslint/js": "^9.3.0",
"@kachurun/storybook-solid": "^8.6.7",
"@kachurun/storybook-solid-vite": "^8.6.7",
"@storybook/addon-essentials": "^8.6.14",
"@storybook/addon-interactions": "^8.6.14",
"@storybook/addon-links": "^8.6.14",
"@storybook/addon-viewport": "^8.6.14",
"@storybook/builder-vite": "^8.6.14",
"@storybook/test-runner": "^0.22.0",
"@tailwindcss/typography": "^0.5.13",
"@types/json-schema": "^7.0.15",
"@types/node": "^22.15.19",
@@ -40,7 +30,6 @@
"postcss-url": "^10.1.3",
"prettier": "^3.2.5",
"solid-devtools": "^0.34.0",
"storybook": "^8.6.14",
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5",
"typescript-eslint": "^8.32.1",

View File

@@ -10,7 +10,7 @@ import {
import { Portal } from "solid-js/web";
import { useFloating } from "../base";
import { autoUpdate, flip, hide, offset, shift, size } from "@floating-ui/dom";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import {
InputBase,
InputError,

View File

@@ -20,7 +20,7 @@ import { createEffect, For, JSX, Match, Show, Switch } from "solid-js";
import cx from "classnames";
import { Label } from "../base/label";
import { SelectInput } from "../fields/Select";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
function generateDefaults(schema: JSONSchema7): unknown {

View File

@@ -5,7 +5,7 @@ import {
SubmitHandler,
} from "@modular-forms/solid";
import { TextInput } from "@/src/Form/fields/TextInput";
import { Button } from "./components/Button/Button";
import { Button } from "./components/button";
import { callApi } from "./api";
import { API } from "@/api/API";
import { createSignal, Match, Switch } from "solid-js";
@@ -18,7 +18,7 @@ interface APITesterForm extends FieldValues {
payload: string;
}
export const ApiTester = () => {
const ApiTester = () => {
const [persistedTestData, setPersistedTestData] = makePersisted(
createSignal<APITesterForm>(),
{
@@ -103,3 +103,5 @@ export const ApiTester = () => {
</div>
);
};
export default ApiTester;

View File

@@ -1,5 +1,5 @@
import { useNavigate } from "@solidjs/router";
import { Button } from "./Button/Button";
import { Button } from "./button";
import Icon from "./icon";
export const BackButton = () => {

View File

@@ -1,43 +0,0 @@
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
import { Button, ButtonProps } from "./Button";
import FlashIcon from "@/icons/flash.svg";
const meta: Meta<ButtonProps> = {
title: "Components/Button",
component: Button,
};
export default meta;
type Story = StoryObj<ButtonProps>;
const children = "click me";
const startIcon = <FlashIcon width={16} height={16} viewBox="0 0 48 48" />;
export const Default: Story = {
args: {
children,
startIcon,
},
};
export const Small: Story = {
args: {
...Default.args,
size: "s",
},
};
export const Light: Story = {
args: {
...Default.args,
variant: "light",
},
};
export const Ghost: Story = {
args: {
...Default.args,
variant: "ghost",
},
};

View File

@@ -9,7 +9,7 @@ import {
shift,
} from "@floating-ui/dom";
import cx from "classnames";
import { Button } from "./Button/Button";
import { Button } from "./button";
interface MenuProps {
/**

View File

@@ -1,12 +1,12 @@
import { For, type JSX, Show } from "solid-js";
import { RouteSectionProps } from "@solidjs/router";
import { AppRoute, routes } from "@/src";
import { SidebarHeader } from "./SidebarHeader";
import { SidebarListItem } from "./SidebarListItem";
import { Typography } from "../Typography";
import "./css/sidebar.css";
import Icon, { IconVariant } from "../icon";
import { clanMetaQuery } from "@/src/queries/clan-meta";
import routes, { AppRoute } from "@/src/routes";
export const SidebarSection = (props: {
title: string;

View File

@@ -1,10 +0,0 @@
textarea {
@apply flex w-full;
@apply border rounded-md p-2;
@apply text-xs;
color: var(--clr-fg-inv-3);
background-color: var(--clr-bg-inv-5);
font-family: "VT323", monospace;
}

View File

@@ -1,19 +0,0 @@
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
import Terminal, { TerminalProps } from "./Terminal";
import sample from "./sample";
const meta: Meta<TerminalProps> = {
title: "Components/Terminal",
component: Terminal,
};
export default meta;
type Story = StoryObj<TerminalProps>;
export const Default: Story = {
args: {
lines: sample.split("\n"),
},
};

View File

@@ -1,28 +0,0 @@
import { Component, createEffect } from "solid-js";
import "./Terminal.css";
import { Typography } from "@/src/components/Typography";
export interface TerminalProps {
lines: string[];
rows?: number;
}
const Terminal: Component<TerminalProps> = ({ lines, rows = 20 }) => {
let ref: HTMLTextAreaElement | undefined;
createEffect(() => {
// always scroll to the end of the output when it changes
if (ref) {
ref.scrollTop = ref.scrollHeight;
}
});
const value = lines.join("\n");
return (
<textarea ref={ref} readOnly={true} rows={rows} value={value}></textarea>
);
};
export default Terminal;

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ import "./css/typography.css";
export type Hierarchy = "body" | "title" | "headline" | "label";
type Color = "primary" | "secondary" | "tertiary";
type Weight = "normal" | "medium" | "bold";
type Tag = "span" | "p" | "h1" | "h2" | "h3" | "h4" | "div" | "textarea";
type Tag = "span" | "p" | "h1" | "h2" | "h3" | "h4" | "div";
const colorMap: Record<Color, string> = {
primary: cx("fnt-clr-primary"),

View File

@@ -1,6 +1,6 @@
import { createSignal, JSX, Show } from "solid-js";
import Icon from "../icon";
import { Button } from "../Button/Button";
import { Button } from "../button";
import cx from "classnames";
import "./accordion.css";

View File

@@ -0,0 +1,27 @@
import { Button } from ".";
import FlashIcon from "@/icons/flash.svg";
export const Test = () => {
<div class="p-8">
<Button>Label</Button>
<Button
startIcon={<FlashIcon width={16} height={16} viewBox="0 0 48 48" />}
>
Label
</Button>
<Button
variant="light"
endIcon={<FlashIcon width={16} height={16} viewBox="0 0 48 48" />}
>
Label
</Button>
<Button size="s">Label</Button>
<Button
variant="light"
size="s"
endIcon={<FlashIcon width={13} height={13} viewBox="0 0 48 48" />}
>
Label
</Button>
</div>;
};

View File

@@ -1,6 +1,6 @@
@import "Button-Light.css";
@import "Button-Dark.css";
@import "Button-Ghost.css";
@import "./button-light.css";
@import "./button-dark.css";
@import "./button-ghost.css";
.button {
@apply inline-flex items-center flex-shrink gap-1 justify-center p-4 font-semibold;

View File

@@ -1,8 +1,8 @@
import { splitProps, type JSX } from "solid-js";
import cx from "classnames";
import { Typography } from "../Typography";
import "./Button-Base.css";
//import './css/index.css'
import "./css/index.css";
type Variants = "dark" | "light" | "ghost";
type Size = "default" | "s";
@@ -42,8 +42,7 @@ const sizeFont: Record<Size, string> = {
s: cx("text-[0.75rem]"),
};
export interface ButtonProps
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
interface ButtonProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: Variants;
size?: Size;
children?: JSX.Element;

View File

@@ -1,6 +1,6 @@
import Dialog from "corvu/dialog";
import { createSignal, JSX } from "solid-js";
import { Button } from "../Button/Button";
import { Button } from "../button";
import Icon from "../icon";
import cx from "classnames";

View File

@@ -24,12 +24,6 @@
src: url(../.fonts/ArchivoSemiCondensed-SemiBold.woff2) format("woff2");
}
@font-face {
font-family: "VT323";
font-weight: normal;
src: url("../.fonts/VT323-Regular.ttf") format("ttf");
}
@keyframes slide {
to {
background-position: 200% 0;

View File

@@ -1,29 +1,13 @@
/* @refresh reload */
import { Portal, render } from "solid-js/web";
import { Navigate, RouteDefinition, Router } from "@solidjs/router";
import { Router } from "@solidjs/router";
import "./index.css";
import { QueryClient, QueryClientProvider } from "@tanstack/solid-query";
import {
CreateMachine,
MachineDetails,
MachineListView,
} from "./routes/machines";
import { Layout } from "./layout/layout";
import { ClanDetails, ClanList, CreateClan } from "./routes/clans";
import { Flash } from "./routes/flash/view";
import { HostList } from "./routes/hosts/view";
import { Welcome } from "./routes/welcome";
import { Toaster } from "solid-toast";
import { ModuleList } from "./routes/modules/list";
import { ModuleDetails } from "./routes/modules/details";
import { ModuleDetails as AddModule } from "./routes/modules/add";
import { ApiTester } from "./api_test";
import { IconVariant } from "./components/icon";
import { Components } from "./routes/components";
import { VarsPage } from "./routes/machines/install/vars-step";
import { ThreePlayground } from "./three";
import { ClanProvider } from "./contexts/clan";
import routes from "@/src/routes";
export const client = new QueryClient();
@@ -40,145 +24,6 @@ if (import.meta.env.DEV) {
await import("solid-devtools");
}
export type AppRoute = Omit<RouteDefinition, "children"> & {
label: string;
icon?: IconVariant;
children?: AppRoute[];
hidden?: boolean;
};
export const routes: AppRoute[] = [
{
path: "/",
label: "",
hidden: true,
component: () => <Navigate href="/machines" />,
},
{
path: "/machines",
label: "Machines",
icon: "Grid",
children: [
{
path: "/",
label: "Overview",
component: () => <MachineListView />,
},
{
path: "/create",
label: "Create",
component: () => <CreateMachine />,
},
{
path: "/:id",
label: "Details",
hidden: true,
component: () => <MachineDetails />,
},
{
path: "/:id/vars",
label: "Vars",
hidden: true,
component: () => <VarsPage />,
},
],
},
{
path: "/clans",
label: "Clans",
hidden: true,
icon: "List",
children: [
{
path: "/",
label: "Overview",
component: () => <ClanList />,
},
{
path: "/create",
label: "Create",
component: () => <CreateClan />,
},
{
path: "/:id",
label: "Details",
hidden: true,
component: () => <ClanDetails />,
},
],
},
{
path: "/modules",
label: "Modules",
icon: "Search",
children: [
{
path: "/",
label: "App Store",
component: () => <ModuleList />,
},
{
path: "details/:id",
label: "Details",
hidden: true,
component: () => <ModuleDetails />,
},
{
path: "/add/:id",
label: "Details",
hidden: true,
component: () => <AddModule />,
},
],
},
{
path: "/tools",
label: "Tools",
icon: "Folder",
children: [
{
path: "/flash",
label: "Flash Installer",
component: () => <Flash />,
},
],
},
{
path: "/welcome",
label: "",
hidden: true,
component: () => <Welcome />,
},
{
path: "/internal-dev",
label: "Internal (Only visible in dev mode)",
children: [
{
path: "/hosts",
label: "Local Hosts",
component: () => <HostList />,
},
{
path: "/3d",
label: "3D-Playground",
component: () => <ThreePlayground />,
},
{
path: "/api_testing",
label: "api_testing",
hidden: false,
component: () => <ApiTester />,
},
{
path: "/components",
label: "Components",
hidden: false,
component: () => <Components />,
},
],
},
];
render(
() => (
<>

View File

@@ -9,7 +9,7 @@ import {
import toast from "solid-toast";
import { TextInput } from "@/src/Form/fields/TextInput";
import { useNavigate } from "@solidjs/router";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { useClanContext } from "@/src/contexts/clan";
@@ -17,7 +17,7 @@ type CreateForm = Meta & {
template: string;
};
export const CreateClan = () => {
const CreateClan = () => {
const [formStore, { Form, Field }] = createForm<CreateForm>({
initialValues: {
name: "",
@@ -205,3 +205,5 @@ type Meta = Extract<
OperationResponse<"show_clan_meta">,
{ status: "success" }
>["data"];
export default CreateClan;

View File

@@ -13,7 +13,7 @@ import {
} from "@modular-forms/solid";
import { TextInput } from "@/src/Form/fields/TextInput";
import toast from "solid-toast";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { Header } from "@/src/layout/header";
import { clanMetaQuery } from "@/src/queries/clan-meta";
@@ -139,7 +139,7 @@ const EditClanForm = (props: EditClanFormProps) => {
type GeneralData = SuccessQuery<"show_clan_meta">["data"];
export const ClanDetails = () => {
const ClanDetails = () => {
const params = useParams();
const clan_dir = window.atob(params.id);
// Fetch general meta data
@@ -158,3 +158,5 @@ export const ClanDetails = () => {
</>
);
};
export default ClanDetails;

View File

@@ -1,3 +0,0 @@
export * from "./list";
export * from "./create";
export * from "./details";

View File

@@ -3,7 +3,7 @@ import { useFloating } from "@/src/floating";
import { autoUpdate, flip, hide, offset, shift } from "@floating-ui/dom";
import { A, useNavigate } from "@solidjs/router";
import { registerClan } from "@/src/hooks";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { useClanContext } from "@/src/contexts/clan";
import { clanURIs, setActiveClanURI } from "@/src/stores/clan";
@@ -124,7 +124,7 @@ const ClanItem = (props: ClanItemProps) => {
);
};
export const ClanList = () => {
const ClanList = () => {
const navigate = useNavigate();
return (
<div class="">
@@ -158,3 +158,5 @@ export const ClanList = () => {
</div>
);
};
export default ClanList;

View File

@@ -1,4 +1,4 @@
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import { InputBase, InputLabel } from "@/src/components/inputBase";
import { TextInput } from "@/src/Form/fields";
import { Header } from "@/src/layout/header";
@@ -8,7 +8,7 @@ const disabled = [false, true];
const readOnly = [false, true];
const error = [false, true];
export const Components = () => {
const Components = () => {
const [formStore, { Form, Field }] = createForm<{ ef: string }>({});
return (
<>
@@ -116,3 +116,5 @@ export const Components = () => {
</>
);
};
export default Components;

View File

@@ -2,7 +2,7 @@ import { callApi } from "@/src/api";
import { useQuery } from "@tanstack/solid-query";
import { useClanContext } from "@/src/contexts/clan";
export function DiskView() {
const DiskView = () => {
const { activeClanURI } = useClanContext();
const query = useQuery(() => ({
@@ -28,4 +28,6 @@ export function DiskView() {
</p>
</div>
);
}
};
export default DiskView;

View File

@@ -1,5 +1,5 @@
import { callApi } from "@/src/api";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
// Icon is used in CustomFileField, ensure it's available or remove if not needed there
import Icon from "@/src/components/icon";
import { Typography } from "@/src/components/Typography";
@@ -46,7 +46,7 @@ export interface FlashFormValues extends FieldValues {
sshKeys: File[]; // This field will use CustomFileField
}
export const Flash = () => {
const Flash = () => {
const [formStore, { Form, Field }] = createForm<FlashFormValues>({
initialValues: {
machine: {
@@ -436,3 +436,5 @@ export const Flash = () => {
</>
);
};
export default Flash;

View File

@@ -1,6 +1,6 @@
import { type Component, createSignal, For, Show } from "solid-js";
import { OperationResponse, callApi } from "@/src/api";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
type ServiceModel = Extract<
@@ -8,7 +8,7 @@ type ServiceModel = Extract<
{ status: "success" }
>["data"]["services"];
export const HostList: Component = () => {
const HostList: Component = () => {
const [services, setServices] = createSignal<ServiceModel>();
return (
@@ -74,3 +74,5 @@ export const HostList: Component = () => {
</div>
);
};
export default HostList;

View File

@@ -0,0 +1,146 @@
import { Navigate, RouteDefinition } from "@solidjs/router";
import { IconVariant } from "@/src/components/icon";
import { lazy } from "solid-js";
export type AppRoute = Omit<RouteDefinition, "children"> & {
label: string;
icon?: IconVariant;
children?: AppRoute[];
hidden?: boolean;
};
const lazyLoad = (path: string) => lazy(() => import(path));
const routes: AppRoute[] = [
{
path: "/",
label: "",
hidden: true,
component: () => <Navigate href="/machines" />,
},
{
path: "/machines",
label: "Machines",
icon: "Grid",
children: [
{
path: "/",
label: "Overview",
component: lazyLoad("./machines/list"),
},
{
path: "/create",
label: "Create",
component: lazyLoad("./machines/create"),
},
{
path: "/:id",
label: "Details",
hidden: true,
component: lazyLoad("./machines/details"),
},
{
path: "/:id/vars",
label: "Vars",
hidden: true,
component: lazyLoad("./machines/install/vars-step"),
},
],
},
{
path: "/clans",
label: "Clans",
hidden: true,
icon: "List",
children: [
{
path: "/",
label: "Overview",
component: lazyLoad("./clans/list"),
},
{
path: "/create",
label: "Create",
component: lazyLoad("./clans/create"),
},
{
path: "/:id",
label: "Details",
hidden: true,
component: lazyLoad("./clans/details"),
},
],
},
{
path: "/modules",
label: "Modules",
icon: "Search",
children: [
{
path: "/",
label: "App Store",
component: lazyLoad("./modules/list"),
},
{
path: "details/:id",
label: "Details",
hidden: true,
component: lazyLoad("./modules/details"),
},
{
path: "/add/:id",
label: "Details",
hidden: true,
component: lazyLoad("./modules/add"),
},
],
},
{
path: "/tools",
label: "Tools",
icon: "Folder",
children: [
{
path: "/flash",
label: "Flash Installer",
component: lazyLoad("./flash/view"),
},
],
},
{
path: "/welcome",
label: "",
hidden: true,
component: lazyLoad("./welcome"),
},
{
path: "/internal-dev",
label: "Internal (Only visible in dev mode)",
children: [
{
path: "/hosts",
label: "Local Hosts",
component: lazyLoad("./hosts/list"),
},
{
path: "/3d",
label: "3D-Playground",
component: lazyLoad("../three"),
},
{
path: "/api_testing",
label: "api_testing",
hidden: false,
component: lazyLoad("../api_test"),
},
{
path: "/components",
label: "Components",
hidden: false,
component: lazyLoad("./components"),
},
],
},
];
export default routes;

View File

@@ -1,5 +1,5 @@
import { callApi, OperationArgs } from "@/src/api";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { TextInput } from "@/src/Form/fields/TextInput";
import { Header } from "@/src/layout/header";
@@ -16,7 +16,7 @@ import { useClanContext } from "@/src/contexts/clan";
type CreateMachineForm = OperationArgs<"create_machine">;
export function CreateMachine() {
const CreateMachine = () => {
const navigate = useNavigate();
const { activeClanURI } = useClanContext();
@@ -189,4 +189,6 @@ export function CreateMachine() {
</div>
</>
);
}
};
export default CreateMachine;

View File

@@ -10,7 +10,7 @@ import { useNavigate, useParams, useSearchParams } from "@solidjs/router";
import { createQuery, useQuery, useQueryClient } from "@tanstack/solid-query";
import { createEffect, createSignal, For, Match, Show, Switch } from "solid-js";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { TextInput } from "@/src/Form/fields/TextInput";
import Accordion from "@/src/components/accordion";
@@ -699,7 +699,7 @@ const MachineForm = (props: MachineDetailsProps) => {
);
};
export const MachineDetails = () => {
const MachineDetails = () => {
const params = useParams();
const { activeClanURI } = useClanContext();
@@ -735,3 +735,5 @@ export const MachineDetails = () => {
</>
);
};
export default MachineDetails;

View File

@@ -1,3 +0,0 @@
export * from "./details";
export * from "./create";
export * from "./list";

View File

@@ -1,5 +1,5 @@
import { callApi } from "@/src/api";
import { Button } from "../../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { InputError, InputLabel } from "@/src/components/inputBase";
import { FieldLayout } from "@/src/Form/fields/layout";

View File

@@ -14,7 +14,7 @@ import toast from "solid-toast";
import { useNavigate, useParams, useSearchParams } from "@solidjs/router";
import { StepProps } from "./hardware-step";
import { BackButton } from "@/src/components/BackButton";
import { Button } from "../../../components/Button/Button";
import { Button } from "@/src/components/button";
import { useClanContext } from "@/src/contexts/clan";
export type VarsValues = FieldValues & Record<string, Record<string, string>>;
@@ -203,7 +203,7 @@ export const VarsStep = (props: VarsStepProps) => {
);
};
export const VarsPage = () => {
const VarsPage = () => {
const params = useParams();
const navigate = useNavigate();
const { activeClanURI } = useClanContext();
@@ -249,3 +249,5 @@ export const VarsPage = () => {
</div>
);
};
export default VarsPage;

View File

@@ -3,7 +3,7 @@ import { callApi, OperationResponse } from "@/src/api";
import { MachineListItem } from "@/src/components/machine-list-item";
import { useQuery, useQueryClient } from "@tanstack/solid-query";
import { useNavigate } from "@solidjs/router";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { Header } from "@/src/layout/header";
import { makePersisted } from "@solid-primitives/storage";
@@ -18,7 +18,7 @@ export interface Filter {
tags: string[];
}
export const MachineListView: Component = () => {
const MachineListView: Component = () => {
const queryClient = useQueryClient();
const [filter, setFilter] = createSignal<Filter>({ tags: [] });
@@ -213,3 +213,5 @@ export const MachineListView: Component = () => {
</>
);
};
export default MachineListView;

View File

@@ -7,7 +7,7 @@ import { createForm, FieldValues, SubmitHandler } from "@modular-forms/solid";
import { SelectInput } from "@/src/Form/fields/Select";
import { useClanContext } from "@/src/contexts/clan";
export const ModuleDetails = () => {
const ModuleDetails = () => {
const params = useParams();
const { activeClanURI } = useClanContext();
const modulesQuery = createModulesQuery(activeClanURI());
@@ -27,6 +27,8 @@ export const ModuleDetails = () => {
);
};
export default ModuleDetails;
interface AddModuleProps {
data: ModuleInfo;
id: string;

View File

@@ -7,12 +7,12 @@ import { createQuery } from "@tanstack/solid-query";
import { JSONSchema7 } from "json-schema";
import { SubmitHandler } from "@modular-forms/solid";
import { DynForm } from "@/src/Form/form";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import Icon from "@/src/components/icon";
import { useClanContext } from "@/src/contexts/clan";
import { activeClanURI } from "@/src/stores/clan";
export const ModuleDetails = () => {
const ModuleDetails = () => {
const params = useParams();
const { activeClanURI } = useClanContext();
const modulesQuery = createModulesQuery(activeClanURI());
@@ -32,6 +32,8 @@ export const ModuleDetails = () => {
);
};
export default ModuleDetails;
function deepMerge(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
obj1: Record<string, any>,

View File

@@ -1,5 +1,5 @@
import { SuccessData } from "@/src/api";
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import { Header } from "@/src/layout/header";
import { createModulesQuery } from "@/src/queries";
import { A, useNavigate } from "@solidjs/router";
@@ -108,7 +108,7 @@ const ModuleItem = (props: {
);
};
export const ModuleList = () => {
const ModuleList = () => {
const queryClient = useQueryClient();
const { activeClanURI } = useClanContext();
const modulesQuery = createModulesQuery(activeClanURI(), {
@@ -214,3 +214,5 @@ export const ModuleList = () => {
</>
);
};
export default ModuleList;

View File

@@ -1,9 +1,9 @@
import { Button } from "../../components/Button/Button";
import { Button } from "@/src/components/button";
import { registerClan } from "@/src/hooks";
import { useNavigate } from "@solidjs/router";
import { useClanContext } from "@/src/contexts/clan";
export const Welcome = () => {
const Welcome = () => {
const navigate = useNavigate();
const { setActiveClanURI } = useClanContext();
return (
@@ -35,3 +35,5 @@ export const Welcome = () => {
</div>
);
};
export default Welcome;

View File

@@ -1,6 +1,6 @@
import { createEffect, createSignal, onCleanup, onMount, Show } from "solid-js";
import * as THREE from "three";
import { Button } from "./components/Button/Button";
import { Button } from "./components/button";
import Icon from "./components/icon";
function addCubesSpiral({
@@ -230,7 +230,7 @@ const View = (props: ViewProps) => {
);
};
export const ThreePlayground = () => {
const ThreePlayground = () => {
const [count, setCount] = createSignal(1);
const [selected, setSelected] = createSignal<string>("");
@@ -269,3 +269,5 @@ export const ThreePlayground = () => {
</div>
);
};
export default ThreePlayground;

View File

@@ -1,8 +1,4 @@
{
"exclude": [
// ignore storybook stories
"**/*.stories.tsx"
],
"compilerOptions": {
"strict": true,
"target": "ESNext",

View File

@@ -3,13 +3,13 @@ import logging
from clan_lib.backups.create import create_backup
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_cli.completions import (
add_dynamic_completer,
complete_backup_providers_for_machine,
complete_machines,
)
from clan_cli.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -2,13 +2,13 @@ import argparse
from clan_lib.backups.list import list_backups
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_cli.completions import (
add_dynamic_completer,
complete_backup_providers_for_machine,
complete_machines,
)
from clan_cli.machines.machines import Machine
def list_command(args: argparse.Namespace) -> None:

View File

@@ -2,13 +2,13 @@ import argparse
from clan_lib.backups.restore import restore_backup
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_cli.completions import (
add_dynamic_completer,
complete_backup_providers_for_machine,
complete_machines,
)
from clan_cli.machines.machines import Machine
def restore_command(args: argparse.Namespace) -> None:

View File

@@ -7,7 +7,6 @@ from clan_lib.cmd import run
from clan_lib.dirs import machine_gcroot
from clan_lib.errors import ClanError
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from clan_lib.nix import (
nix_add_to_gcroots,
nix_build,
@@ -17,6 +16,7 @@ from clan_lib.nix import (
)
from clan_cli.machines.list import list_machines
from clan_cli.machines.machines import Machine
from clan_cli.vms.inspect import VmConfig, inspect_vm

View File

@@ -1,9 +1,8 @@
import argparse
import logging
from clan_lib.machines.machines import Machine
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -10,7 +10,6 @@ from tempfile import TemporaryDirectory
from clan_lib.cmd import RunOpts, run
from clan_lib.errors import ClanError
from clan_lib.git import commit_files
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_shell
from clan_cli.completions import (
@@ -19,6 +18,7 @@ from clan_cli.completions import (
complete_services_for_machine,
)
from clan_cli.machines.list import list_machines
from clan_cli.machines.machines import Machine
from .check import check_secrets
from .public_modules import FactStoreBase

View File

@@ -2,9 +2,8 @@ import argparse
import json
import logging
from clan_lib.machines.machines import Machine
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from abc import ABC, abstractmethod
from pathlib import Path
import clan_lib.machines.machines as machines
import clan_cli.machines.machines as machines
class FactStoreBase(ABC):

View File

@@ -1,7 +1,8 @@
from pathlib import Path
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
from . import FactStoreBase

View File

@@ -3,7 +3,8 @@ from pathlib import Path
from clan_lib.dirs import vm_state_dir
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
from . import FactStoreBase

View File

@@ -3,9 +3,10 @@ from __future__ import annotations
from abc import ABC, abstractmethod
from pathlib import Path
import clan_lib.machines.machines as machines
from clan_lib.ssh.remote import Remote
import clan_cli.machines.machines as machines
class SecretStoreBase(ABC):
@abstractmethod

View File

@@ -4,11 +4,11 @@ from pathlib import Path
from typing import override
from clan_lib.cmd import Log, RunOpts
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_shell
from clan_lib.ssh.remote import Remote
from clan_cli.facts.secret_modules import SecretStoreBase
from clan_cli.machines.machines import Machine
class SecretStore(SecretStoreBase):

View File

@@ -1,9 +1,9 @@
from pathlib import Path
from typing import override
from clan_lib.machines.machines import Machine
from clan_lib.ssh.remote import Remote
from clan_cli.machines.machines import Machine
from clan_cli.secrets.folders import sops_secrets_folder
from clan_cli.secrets.machines import add_machine, has_machine
from clan_cli.secrets.secrets import decrypt_secret, encrypt_secret, has_secret

View File

@@ -3,7 +3,8 @@ from pathlib import Path
from typing import override
from clan_lib.dirs import vm_state_dir
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
from . import SecretStoreBase

View File

@@ -3,9 +3,8 @@ import logging
from pathlib import Path
from tempfile import TemporaryDirectory
from clan_lib.machines.machines import Machine
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
from clan_cli.ssh.upload import upload
log = logging.getLogger(__name__)

View File

@@ -6,7 +6,8 @@ from pathlib import Path
from clan_lib.cmd import Log, RunOpts, run
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -9,10 +9,10 @@ from typing import Any
from clan_lib.api import API
from clan_lib.cmd import Log, RunOpts, cmd_with_root, run
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_shell
from clan_cli.facts.generate import generate_facts
from clan_cli.machines.machines import Machine
from clan_cli.vars.generate import generate_vars
from clan_cli.vars.upload import populate_secret_vars

View File

@@ -7,9 +7,9 @@ from pathlib import Path
from typing import Any
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
from .flash import Disk, SystemConfig, flash_machine

View File

@@ -6,9 +6,9 @@ from pathlib import Path
from clan_lib import inventory
from clan_lib.api import API
from clan_lib.dirs import specific_machine_dir
from clan_lib.machines.machines import Machine
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
from clan_cli.secrets.folders import sops_secrets_folder
from clan_cli.secrets.machines import has_machine as secrets_has_machine
from clan_cli.secrets.machines import remove_machine as secrets_machine_remove

View File

@@ -10,10 +10,10 @@ from clan_lib.cmd import RunOpts, run
from clan_lib.dirs import specific_machine_dir
from clan_lib.errors import ClanCmdError, ClanError
from clan_lib.git import commit_file
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_config, nix_eval
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
from .types import machine_name_type

View File

@@ -10,7 +10,6 @@ from tempfile import TemporaryDirectory
from clan_lib.api import API
from clan_lib.cmd import Log, RunOpts, run
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_shell
from clan_cli.completions import (
@@ -20,6 +19,7 @@ from clan_cli.completions import (
)
from clan_cli.facts.generate import generate_facts
from clan_cli.machines.hardware import HardwareConfig
from clan_cli.machines.machines import Machine
from clan_cli.ssh.deploy_info import DeployInfo, find_reachable_host, ssh_command_parse
from clan_cli.ssh.host_key import HostKeyCheck
from clan_cli.vars.generate import generate_vars

View File

@@ -1,12 +1,13 @@
from clan_lib.api import API
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_lib.nix_models.inventory import (
Machine as InventoryMachine,
)
from clan_lib.persist.inventory_store import InventoryStore
from clan_lib.persist.util import apply_patch
from clan_cli.machines.machines import Machine
@API.register
def get_machine(machine: Machine) -> InventoryMachine:

View File

@@ -9,13 +9,13 @@ from clan_lib.api.modules import parse_frontmatter
from clan_lib.dirs import specific_machine_dir
from clan_lib.errors import ClanError
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from clan_lib.nix_models.inventory import Machine as InventoryMachine
from clan_lib.persist.inventory_store import InventoryStore
from clan_cli.completions import add_dynamic_completer, complete_tags
from clan_cli.machines.hardware import HardwareConfig
from clan_cli.machines.inventory import get_machine
from clan_cli.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -7,16 +7,16 @@ from functools import cached_property
from pathlib import Path
from typing import TYPE_CHECKING, Any
from clan_cli.facts import public_modules as facts_public_modules
from clan_cli.facts import secret_modules as facts_secret_modules
from clan_cli.ssh.host_key import HostKeyCheck
from clan_cli.vars._types import StoreBase
from clan_lib.errors import ClanCmdError, ClanError
from clan_lib.flake import Flake
from clan_lib.nix import nix_config, nix_test_store
from clan_lib.ssh.remote import Remote
from clan_cli.facts import public_modules as facts_public_modules
from clan_cli.facts import secret_modules as facts_secret_modules
from clan_cli.ssh.host_key import HostKeyCheck
from clan_cli.vars._types import StoreBase
log = logging.getLogger(__name__)
if TYPE_CHECKING:

View File

@@ -1,6 +1,7 @@
import pytest
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
# Functions to test
from clan_cli.tests.fixtures_flakes import FlakeForTest

View File

@@ -11,11 +11,11 @@ from clan_lib.cmd import Log, RunOpts, run
from clan_lib.dirs import get_clan_flake_toplevel_or_env
from clan_lib.errors import ClanError
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_build, nix_command
from clan_lib.nix_models.inventory import Machine as InventoryMachine
from clan_cli.machines.create import CreateOptions, create_machine
from clan_cli.machines.machines import Machine
from clan_cli.vars.generate import generate_vars
log = logging.getLogger(__name__)

View File

@@ -11,7 +11,6 @@ from clan_lib.async_run import AsyncContext, AsyncOpts, AsyncRuntime, is_async_c
from clan_lib.cmd import Log, MsgColor, RunOpts, run
from clan_lib.colors import AnsiColor
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_command, nix_config, nix_metadata
from clan_lib.ssh.remote import HostKeyCheck, Remote
@@ -22,6 +21,7 @@ from clan_cli.completions import (
from clan_cli.facts.generate import generate_facts
from clan_cli.facts.upload import upload_secrets
from clan_cli.machines.list import list_machines
from clan_cli.machines.machines import Machine
from clan_cli.vars.generate import generate_vars
from clan_cli.vars.upload import upload_secret_vars

View File

@@ -9,7 +9,6 @@ from typing import Any
from clan_lib.async_run import AsyncRuntime
from clan_lib.cmd import run
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_shell
from clan_lib.ssh.parse import parse_deployment_address
from clan_lib.ssh.remote import Remote, is_ssh_reachable
@@ -18,6 +17,7 @@ from clan_cli.completions import (
add_dynamic_completer,
complete_machines,
)
from clan_cli.machines.machines import Machine
from clan_cli.ssh.host_key import HostKeyCheck
from clan_cli.ssh.tor import TorTarget, spawn_tor, ssh_tor_reachable

View File

@@ -6,7 +6,6 @@ from pathlib import Path
from clan_lib.cmd import RunOpts, run
from clan_lib.dirs import get_clan_flake_toplevel_or_env
from clan_lib.errors import ClanCmdError, ClanError
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_eval
from clan_cli.completions import (
@@ -14,6 +13,7 @@ from clan_cli.completions import (
complete_machines,
complete_state_services_for_machine,
)
from clan_cli.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -10,6 +10,7 @@ from pathlib import Path
from typing import Any, NamedTuple
import pytest
from clan_cli.machines.machines import Machine
from clan_cli.tests import age_keys
from clan_cli.tests.fixture_error import FixtureError
from clan_cli.tests.root import CLAN_CORE
@@ -22,7 +23,6 @@ from clan_lib.dirs import (
)
from clan_lib.flake import Flake
from clan_lib.locked_open import locked_open
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_test_store
log = logging.getLogger(__name__)

View File

@@ -18,8 +18,8 @@ from clan_lib.persist.inventory_store import InventoryStore
if TYPE_CHECKING:
from .age_keys import KeyPair
from clan_cli.machines.machines import Machine as MachineMachine
from clan_cli.tests.helpers import cli
from clan_lib.machines.machines import Machine as MachineMachine
@pytest.mark.with_core

View File

@@ -3,12 +3,12 @@ from typing import TYPE_CHECKING
import pytest
from clan_cli.facts.secret_modules.sops import SecretStore
from clan_cli.machines.machines import Machine
from clan_cli.secrets.folders import sops_secrets_folder
from clan_cli.tests.fixtures_flakes import FlakeForTest
from clan_cli.tests.helpers import cli
from clan_cli.tests.helpers.validator import is_valid_age_key
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
if TYPE_CHECKING:
from .age_keys import KeyPair

View File

@@ -4,6 +4,7 @@ import shutil
from pathlib import Path
import pytest
from clan_cli.machines.machines import Machine
from clan_cli.tests.age_keys import SopsSetup
from clan_cli.tests.fixtures_flakes import ClanFlake
from clan_cli.tests.helpers import cli
@@ -22,7 +23,6 @@ from clan_cli.vars.secret_modules import password_store, sops
from clan_cli.vars.set import set_var
from clan_lib.errors import ClanError
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_eval, run

View File

@@ -4,6 +4,7 @@ import sys
from contextlib import ExitStack
import pytest
from clan_cli.machines.machines import Machine
from clan_cli.tests.age_keys import SopsSetup
from clan_cli.tests.fixtures_flakes import ClanFlake
from clan_cli.tests.helpers import cli
@@ -11,7 +12,6 @@ from clan_cli.tests.nix_config import ConfigItem
from clan_cli.vms.run import inspect_vm, spawn_vm
from clan_lib import cmd
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from clan_lib.nix import nix_eval, run

View File

@@ -2,12 +2,12 @@ from pathlib import Path
from typing import TYPE_CHECKING
import pytest
from clan_cli.machines.machines import Machine
from clan_cli.tests.fixtures_flakes import ClanFlake, FlakeForTest
from clan_cli.tests.helpers import cli
from clan_cli.tests.stdout import CaptureOutput
from clan_cli.vms.run import inspect_vm, spawn_vm
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
if TYPE_CHECKING:
from .age_keys import KeyPair

View File

@@ -5,8 +5,8 @@ from dataclasses import dataclass
from pathlib import Path
from typing import TYPE_CHECKING
from clan_cli.machines import machines
from clan_lib.errors import ClanError
from clan_lib.machines import machines
from clan_lib.ssh.remote import Remote
if TYPE_CHECKING:

View File

@@ -2,8 +2,8 @@ import argparse
import logging
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -2,8 +2,8 @@ import argparse
import logging
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
log = logging.getLogger(__name__)

View File

@@ -35,7 +35,7 @@ from .var import Var
log = logging.getLogger(__name__)
if TYPE_CHECKING:
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
@dataclass
@@ -356,7 +356,7 @@ def get_generators_closure(
full_closure: bool = False,
include_previous_values: bool = False,
) -> list[Generator]:
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
return get_closure(
machine=Machine(name=machine_name, flake=Flake(str(base_dir))),
@@ -395,7 +395,7 @@ def generate_vars_for_machine(
base_dir: Path,
no_sandbox: bool = False,
) -> bool:
from clan_lib.machines.machines import Machine
from clan_cli.machines.machines import Machine
machine = Machine(name=machine_name, flake=Flake(str(base_dir)))
generators_set = set(generators)

View File

@@ -2,10 +2,10 @@ import argparse
import logging
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.machines.machines import Machine
from clan_lib.api import API
from clan_lib.errors import ClanError
from clan_lib.flake import Flake
from clan_lib.machines.machines import Machine
from ._types import GeneratorUpdate
from .generate import Generator, Prompt, Var, execute_generator

View File

@@ -8,8 +8,8 @@ from clan_lib.git import commit_files
log = logging.getLogger(__name__)
if TYPE_CHECKING:
from clan_cli.machines.machines import Machine
from clan_cli.vars.generate import Generator
from clan_lib.machines.machines import Machine
def _migration_file_exists(

View File

@@ -2,10 +2,10 @@ import shutil
from collections.abc import Iterable
from pathlib import Path
from clan_cli.machines.machines import Machine
from clan_cli.vars._types import StoreBase
from clan_cli.vars.generate import Generator, Var
from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine
from clan_lib.ssh.remote import Remote

Some files were not shown because too many files have changed in this diff Show More