@valentinkolb/cloud 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +69 -0
- package/public/logo.svg +1 -0
- package/scripts/build.ts +113 -0
- package/scripts/preload.ts +73 -0
- package/src/_internal/define-app.ts +399 -0
- package/src/_internal/heartbeat.ts +33 -0
- package/src/_internal/registry.ts +100 -0
- package/src/_internal/runtime-context.ts +38 -0
- package/src/api/accounts-entities.ts +134 -0
- package/src/api/admin-lifecycle.ts +210 -0
- package/src/api/auth/schemas.ts +28 -0
- package/src/api/auth.ts +230 -0
- package/src/api/index.ts +66 -0
- package/src/api/me.ts +206 -0
- package/src/api/search/schemas.ts +43 -0
- package/src/api/search.ts +130 -0
- package/src/clients/core.ts +19 -0
- package/src/config/env.ts +23 -0
- package/src/config/index.ts +6 -0
- package/src/config/ssr.ts +58 -0
- package/src/contracts/app.ts +140 -0
- package/src/contracts/index.ts +5 -0
- package/src/contracts/profile.ts +67 -0
- package/src/contracts/registry.ts +50 -0
- package/src/contracts/settings-types.ts +84 -0
- package/src/contracts/shared.ts +258 -0
- package/src/contracts/widgets.ts +121 -0
- package/src/index.ts +6 -0
- package/src/server/api/index.ts +1 -0
- package/src/server/api/respond.ts +55 -0
- package/src/server/api-client.ts +54 -0
- package/src/server/app-context.ts +39 -0
- package/src/server/index.ts +62 -0
- package/src/server/middleware/auth.ts +168 -0
- package/src/server/middleware/index.ts +7 -0
- package/src/server/middleware/middleware.ts +47 -0
- package/src/server/middleware/openapi.ts +126 -0
- package/src/server/middleware/rate-limit.ts +126 -0
- package/src/server/middleware/request-logger.ts +41 -0
- package/src/server/middleware/validator.ts +35 -0
- package/src/server/services/access.ts +294 -0
- package/src/server/services/freeipa/client.ts +100 -0
- package/src/server/services/freeipa/index.ts +9 -0
- package/src/server/services/freeipa/session.ts +78 -0
- package/src/server/services/freeipa/tls.ts +48 -0
- package/src/server/services/freeipa/util.ts +60 -0
- package/src/server/services/geo.ts +154 -0
- package/src/server/services/index.ts +28 -0
- package/src/server/services/services.ts +13 -0
- package/src/services/account-lifecycle/audit.ts +41 -0
- package/src/services/account-lifecycle/index.ts +907 -0
- package/src/services/account-lifecycle/scheduler.ts +347 -0
- package/src/services/account-model.ts +21 -0
- package/src/services/accounts/app.ts +966 -0
- package/src/services/accounts/authz.ts +22 -0
- package/src/services/accounts/base-group.ts +11 -0
- package/src/services/accounts/base-user.ts +45 -0
- package/src/services/accounts/entities.ts +529 -0
- package/src/services/accounts/group-sql.ts +106 -0
- package/src/services/accounts/groups.ts +246 -0
- package/src/services/accounts/index.ts +14 -0
- package/src/services/accounts/ipa-data.ts +64 -0
- package/src/services/accounts/lifecycle.ts +2 -0
- package/src/services/accounts/local-groups.ts +491 -0
- package/src/services/accounts/model.ts +135 -0
- package/src/services/accounts/switching.ts +117 -0
- package/src/services/accounts/users.ts +714 -0
- package/src/services/auth-flows/index.ts +6 -0
- package/src/services/auth-flows/ipa.ts +128 -0
- package/src/services/auth-flows/magic-link.ts +119 -0
- package/src/services/freeipa-config.ts +89 -0
- package/src/services/index.ts +46 -0
- package/src/services/ipa/auth.ts +122 -0
- package/src/services/ipa/groups.ts +684 -0
- package/src/services/ipa/guard.ts +17 -0
- package/src/services/ipa/index.ts +17 -0
- package/src/services/ipa/profile.ts +90 -0
- package/src/services/ipa/search.ts +154 -0
- package/src/services/ipa/sync.ts +740 -0
- package/src/services/ipa/users.ts +794 -0
- package/src/services/logging/index.ts +294 -0
- package/src/services/notifications/email.ts +123 -0
- package/src/services/notifications/index.ts +413 -0
- package/src/services/postgres.ts +51 -0
- package/src/services/providers/index.ts +27 -0
- package/src/services/providers/local/auth.ts +13 -0
- package/src/services/providers/local/index.ts +4 -0
- package/src/services/providers/local/users.ts +255 -0
- package/src/services/session/index.ts +137 -0
- package/src/services/settings/api.ts +61 -0
- package/src/services/settings/app.ts +101 -0
- package/src/services/settings/crypto.ts +69 -0
- package/src/services/settings/defaults.ts +824 -0
- package/src/services/settings/index.ts +203 -0
- package/src/services/settings/namespace.ts +9 -0
- package/src/services/settings/snapshot.ts +49 -0
- package/src/services/settings/store.ts +179 -0
- package/src/services/settings/templates.ts +10 -0
- package/src/services/weather/forecast.ts +287 -0
- package/src/services/weather/geo.ts +110 -0
- package/src/services/weather/index.ts +99 -0
- package/src/services/weather/location.ts +24 -0
- package/src/services/weather/locations.ts +125 -0
- package/src/services/weather/migrate.ts +22 -0
- package/src/services/weather/types.ts +61 -0
- package/src/services/weather/ui.ts +50 -0
- package/src/shared/account-display.ts +17 -0
- package/src/shared/account-session.ts +15 -0
- package/src/shared/icons.ts +109 -0
- package/src/shared/index.ts +10 -0
- package/src/shared/markdown/client.ts +130 -0
- package/src/shared/markdown/extensions/code.ts +58 -0
- package/src/shared/markdown/extensions/images.ts +43 -0
- package/src/shared/markdown/extensions/info-blocks.ts +93 -0
- package/src/shared/markdown/extensions/katex.ts +120 -0
- package/src/shared/markdown/extensions/links.ts +34 -0
- package/src/shared/markdown/extensions/tables.ts +88 -0
- package/src/shared/markdown/extensions/task-list.ts +53 -0
- package/src/shared/markdown/index.ts +97 -0
- package/src/shared/markdown/shared.ts +36 -0
- package/src/ssr/AdminLayout.tsx +42 -0
- package/src/ssr/AdminSidebar.tsx +95 -0
- package/src/ssr/Footer.island.tsx +62 -0
- package/src/ssr/GlobalSearchDialog.tsx +389 -0
- package/src/ssr/GlobalSearchHelpDialog.tsx +106 -0
- package/src/ssr/GlobalSearchTrigger.island.tsx +42 -0
- package/src/ssr/HotkeysHelpRail.island.tsx +99 -0
- package/src/ssr/Layout.tsx +326 -0
- package/src/ssr/MoreAppsDropdown.island.tsx +61 -0
- package/src/ssr/NavMenu.island.tsx +108 -0
- package/src/ssr/ThemeToggleRail.island.tsx +27 -0
- package/src/ssr/index.ts +5 -0
- package/src/ssr/islands/SearchBar.island.tsx +77 -0
- package/src/ssr/islands/index.ts +1 -0
- package/src/ssr/runtime.ts +22 -0
- package/src/styles/base-popover.css +28 -0
- package/src/styles/effects.css +65 -0
- package/src/styles/global.css +133 -0
- package/src/styles/input.css +54 -0
- package/src/styles/tokens.css +35 -0
- package/src/styles/utilities-buttons.css +125 -0
- package/src/styles/utilities-feedback.css +65 -0
- package/src/styles/utilities-layout.css +122 -0
- package/src/styles/utilities-navigation.css +196 -0
- package/src/types/ambient.d.ts +8 -0
- package/src/ui/admin-settings.tsx +148 -0
- package/src/ui/dialog-core.ts +146 -0
- package/src/ui/filter/FilterChip.tsx +196 -0
- package/src/ui/filter/index.ts +2 -0
- package/src/ui/index.ts +19 -0
- package/src/ui/input/Checkbox.tsx +55 -0
- package/src/ui/input/ColorInput.tsx +122 -0
- package/src/ui/input/DateTimeInput.tsx +86 -0
- package/src/ui/input/ImageInput.tsx +170 -0
- package/src/ui/input/NumberInput.tsx +113 -0
- package/src/ui/input/PinInput.tsx +169 -0
- package/src/ui/input/SegmentedControl.tsx +99 -0
- package/src/ui/input/Select.tsx +288 -0
- package/src/ui/input/SelectChip.tsx +61 -0
- package/src/ui/input/Slider.tsx +118 -0
- package/src/ui/input/Switch.tsx +62 -0
- package/src/ui/input/TagsInput.tsx +115 -0
- package/src/ui/input/TextInput.tsx +160 -0
- package/src/ui/input/index.ts +13 -0
- package/src/ui/input/types.ts +42 -0
- package/src/ui/input/util.tsx +105 -0
- package/src/ui/ipa/Avatar.tsx +28 -0
- package/src/ui/ipa/GroupView.tsx +36 -0
- package/src/ui/ipa/LoginBtn.tsx +16 -0
- package/src/ui/ipa/UserView.tsx +58 -0
- package/src/ui/ipa/index.ts +4 -0
- package/src/ui/misc/ContextMenu.tsx +211 -0
- package/src/ui/misc/CopyButton.tsx +28 -0
- package/src/ui/misc/Dropdown.tsx +194 -0
- package/src/ui/misc/EntitySearch.tsx +213 -0
- package/src/ui/misc/Lightbox.tsx +194 -0
- package/src/ui/misc/LinkCard.tsx +34 -0
- package/src/ui/misc/LogEntriesTable.tsx +61 -0
- package/src/ui/misc/MarkdownView.tsx +65 -0
- package/src/ui/misc/Pagination.tsx +51 -0
- package/src/ui/misc/PermissionEditor.tsx +379 -0
- package/src/ui/misc/ProgressBar.tsx +47 -0
- package/src/ui/misc/RemoveBtn.tsx +27 -0
- package/src/ui/misc/StatCell.tsx +90 -0
- package/src/ui/misc/index.ts +18 -0
- package/src/ui/navigation.ts +32 -0
- package/src/ui/prompts.tsx +854 -0
- package/src/ui/sidebar.tsx +468 -0
- package/src/ui/widgets/Widget.tsx +62 -0
- package/src/ui/widgets/WidgetCard.tsx +19 -0
- package/src/ui/widgets/WidgetHero.tsx +39 -0
- package/src/ui/widgets/WidgetList.tsx +84 -0
- package/src/ui/widgets/WidgetPills.tsx +68 -0
- package/src/ui/widgets/WidgetStat.tsx +67 -0
- package/src/ui/widgets/WidgetStatus.tsx +62 -0
- package/src/ui/widgets/index.ts +9 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pills block inside a Widget — flex-wrap row of compact label + value chips.
|
|
5
|
+
* Same visual style as the pill-row pattern used for compact KPIs in admin
|
|
6
|
+
* pages.
|
|
7
|
+
*/
|
|
8
|
+
type Tone = "emerald" | "amber" | "red" | "blue" | "zinc";
|
|
9
|
+
|
|
10
|
+
const PILL_TONE: Record<Tone, string> = {
|
|
11
|
+
emerald: "bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300",
|
|
12
|
+
amber: "bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300",
|
|
13
|
+
red: "bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-300",
|
|
14
|
+
blue: "bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300",
|
|
15
|
+
zinc: "bg-zinc-100 dark:bg-zinc-800/70 text-secondary",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type WidgetPill = {
|
|
19
|
+
label: string;
|
|
20
|
+
value: string | number;
|
|
21
|
+
tone?: Tone;
|
|
22
|
+
href?: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type WidgetPillsProps = {
|
|
26
|
+
pills: WidgetPill[];
|
|
27
|
+
/** Fills remaining vertical space and centres its pills. */
|
|
28
|
+
grow?: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const Pill = (props: { pill: WidgetPill }): JSX.Element => {
|
|
32
|
+
const tone = () => props.pill.tone ?? "zinc";
|
|
33
|
+
const baseClass = () => `inline-flex items-baseline gap-1.5 rounded-md px-2 py-0.5 ${PILL_TONE[tone()]}`;
|
|
34
|
+
const labelTone = () =>
|
|
35
|
+
tone() === "zinc"
|
|
36
|
+
? "uppercase tracking-wider text-[10px] text-dimmed"
|
|
37
|
+
: "uppercase tracking-wider text-[10px]";
|
|
38
|
+
const valueTone = () => "text-xs font-bold tabular-nums";
|
|
39
|
+
|
|
40
|
+
if (props.pill.href) {
|
|
41
|
+
return (
|
|
42
|
+
<a href={props.pill.href} class={`${baseClass()} hover:opacity-80 transition-opacity`}>
|
|
43
|
+
<span class={labelTone()}>{props.pill.label}</span>
|
|
44
|
+
<span class={valueTone()}>{props.pill.value}</span>
|
|
45
|
+
</a>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return (
|
|
49
|
+
<span class={baseClass()}>
|
|
50
|
+
<span class={labelTone()}>{props.pill.label}</span>
|
|
51
|
+
<span class={valueTone()}>{props.pill.value}</span>
|
|
52
|
+
</span>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const WidgetPills = (props: WidgetPillsProps): JSX.Element => (
|
|
57
|
+
<div
|
|
58
|
+
class={`px-4 py-3 flex flex-wrap gap-1.5 ${
|
|
59
|
+
props.grow ? "flex-1 content-center" : ""
|
|
60
|
+
}`}
|
|
61
|
+
>
|
|
62
|
+
{props.pills.map((pill) => (
|
|
63
|
+
<Pill pill={pill} />
|
|
64
|
+
))}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
export default WidgetPills;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stat block inside a Widget — one big number, label, optional sub line and
|
|
5
|
+
* accent. Same conventions as `StatCell` but full-width and with more breathing
|
|
6
|
+
* room for the dashboard rather than the dense admin grid.
|
|
7
|
+
*/
|
|
8
|
+
type Tone = "emerald" | "amber" | "red" | "blue" | "zinc";
|
|
9
|
+
|
|
10
|
+
const ICON_TONE: Record<Tone, string> = {
|
|
11
|
+
emerald: "text-emerald-600 dark:text-emerald-400",
|
|
12
|
+
amber: "text-amber-600 dark:text-amber-400",
|
|
13
|
+
red: "text-red-500 dark:text-red-400",
|
|
14
|
+
blue: "text-blue-600 dark:text-blue-400",
|
|
15
|
+
zinc: "text-zinc-500 dark:text-zinc-400",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const PILL_TONE: Record<Tone, string> = {
|
|
19
|
+
emerald: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300",
|
|
20
|
+
amber: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300",
|
|
21
|
+
red: "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300",
|
|
22
|
+
blue: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300",
|
|
23
|
+
zinc: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type WidgetStatProps = {
|
|
27
|
+
value: string | number;
|
|
28
|
+
label: string;
|
|
29
|
+
sub?: string;
|
|
30
|
+
/** Override the default value colour. */
|
|
31
|
+
valueClass?: string;
|
|
32
|
+
/** Optional accent — text → pill with bg, no text → plain colored icon. */
|
|
33
|
+
accent?: { tone: Tone; icon: string; text?: string };
|
|
34
|
+
/** Fills remaining vertical space inside the widget; content centred. */
|
|
35
|
+
grow?: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const WidgetStat = (props: WidgetStatProps): JSX.Element => {
|
|
39
|
+
const valueClass = () => props.valueClass ?? "text-primary";
|
|
40
|
+
const containerClass = () =>
|
|
41
|
+
props.grow ? "px-4 py-4 flex flex-col gap-1 flex-1 justify-center" : "px-4 py-4 flex flex-col gap-1";
|
|
42
|
+
return (
|
|
43
|
+
<div class={containerClass()}>
|
|
44
|
+
<span class="text-[10px] uppercase tracking-wider text-dimmed">{props.label}</span>
|
|
45
|
+
<span class={`text-3xl font-bold tabular-nums leading-none ${valueClass()}`}>
|
|
46
|
+
{props.value}
|
|
47
|
+
</span>
|
|
48
|
+
{props.sub || props.accent ? (
|
|
49
|
+
<div class="flex items-center gap-1.5">
|
|
50
|
+
{props.sub ? <span class="text-[11px] text-dimmed">{props.sub}</span> : null}
|
|
51
|
+
{props.accent ? (
|
|
52
|
+
props.accent.text ? (
|
|
53
|
+
<span class={`tag ${PILL_TONE[props.accent.tone]}`}>
|
|
54
|
+
<i class={`${props.accent.icon} text-[9px]`} />
|
|
55
|
+
{props.accent.text}
|
|
56
|
+
</span>
|
|
57
|
+
) : (
|
|
58
|
+
<i class={`${props.accent.icon} ${ICON_TONE[props.accent.tone]} text-[12px]`} />
|
|
59
|
+
)
|
|
60
|
+
) : null}
|
|
61
|
+
</div>
|
|
62
|
+
) : null}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default WidgetStat;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Status block inside a Widget — a tinted banner-style row with an icon,
|
|
5
|
+
* title and message. Use to surface health / state at a glance.
|
|
6
|
+
*/
|
|
7
|
+
type Tone = "ok" | "warn" | "error" | "info";
|
|
8
|
+
|
|
9
|
+
const TONE_STYLES: Record<Tone, { bg: string; text: string; icon: string; defaultIcon: string }> = {
|
|
10
|
+
ok: {
|
|
11
|
+
bg: "bg-emerald-50 dark:bg-emerald-900/20",
|
|
12
|
+
text: "text-emerald-800 dark:text-emerald-200",
|
|
13
|
+
icon: "text-emerald-600 dark:text-emerald-400",
|
|
14
|
+
defaultIcon: "ti ti-circle-check",
|
|
15
|
+
},
|
|
16
|
+
warn: {
|
|
17
|
+
bg: "bg-amber-50 dark:bg-amber-900/20",
|
|
18
|
+
text: "text-amber-800 dark:text-amber-200",
|
|
19
|
+
icon: "text-amber-600 dark:text-amber-400",
|
|
20
|
+
defaultIcon: "ti ti-alert-triangle",
|
|
21
|
+
},
|
|
22
|
+
error: {
|
|
23
|
+
bg: "bg-red-50 dark:bg-red-900/20",
|
|
24
|
+
text: "text-red-800 dark:text-red-200",
|
|
25
|
+
icon: "text-red-600 dark:text-red-400",
|
|
26
|
+
defaultIcon: "ti ti-alert-circle",
|
|
27
|
+
},
|
|
28
|
+
info: {
|
|
29
|
+
bg: "bg-blue-50 dark:bg-blue-900/20",
|
|
30
|
+
text: "text-blue-800 dark:text-blue-200",
|
|
31
|
+
icon: "text-blue-600 dark:text-blue-400",
|
|
32
|
+
defaultIcon: "ti ti-info-circle",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type WidgetStatusProps = {
|
|
37
|
+
tone: Tone;
|
|
38
|
+
title: string;
|
|
39
|
+
message?: string;
|
|
40
|
+
icon?: string;
|
|
41
|
+
/** Fills remaining vertical space and centres its content. */
|
|
42
|
+
grow?: boolean;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const WidgetStatus = (props: WidgetStatusProps): JSX.Element => {
|
|
46
|
+
const styles = () => TONE_STYLES[props.tone];
|
|
47
|
+
const containerClass = () =>
|
|
48
|
+
props.grow
|
|
49
|
+
? `px-4 py-3 flex items-center gap-3 ${styles().bg} flex-1`
|
|
50
|
+
: `px-4 py-3 flex items-start gap-3 ${styles().bg}`;
|
|
51
|
+
return (
|
|
52
|
+
<div class={containerClass()}>
|
|
53
|
+
<i class={`${props.icon ?? styles().defaultIcon} ${styles().icon} text-base ${props.grow ? "" : "mt-0.5"} shrink-0`} />
|
|
54
|
+
<div class="flex-1 min-w-0 flex flex-col gap-0.5">
|
|
55
|
+
<span class={`text-xs font-semibold ${styles().text}`}>{props.title}</span>
|
|
56
|
+
{props.message ? <span class={`text-[11px] ${styles().text} opacity-80`}>{props.message}</span> : null}
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default WidgetStatus;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as WidgetCard } from "./WidgetCard";
|
|
2
|
+
export { default as Widget } from "./Widget";
|
|
3
|
+
export { default as WidgetStat } from "./WidgetStat";
|
|
4
|
+
export { default as WidgetList } from "./WidgetList";
|
|
5
|
+
export type { WidgetListItem } from "./WidgetList";
|
|
6
|
+
export { default as WidgetStatus } from "./WidgetStatus";
|
|
7
|
+
export { default as WidgetPills } from "./WidgetPills";
|
|
8
|
+
export type { WidgetPill } from "./WidgetPills";
|
|
9
|
+
export { default as WidgetHero } from "./WidgetHero";
|