@arch-cadre/panel 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/actions/actions.cjs +18 -0
  2. package/dist/actions/actions.d.ts +4 -0
  3. package/dist/actions/actions.mjs +10 -0
  4. package/dist/actions/index.cjs +27 -0
  5. package/dist/actions/index.d.ts +2 -0
  6. package/dist/actions/index.mjs +2 -0
  7. package/dist/actions/manager.cjs +138 -0
  8. package/dist/actions/manager.d.ts +14 -0
  9. package/dist/actions/manager.mjs +135 -0
  10. package/dist/actions/profile.cjs +169 -0
  11. package/dist/actions/profile.d.ts +8 -0
  12. package/dist/actions/profile.mjs +135 -0
  13. package/dist/actions/settings.cjs +26 -0
  14. package/dist/actions/settings.d.ts +7 -0
  15. package/dist/actions/settings.mjs +20 -0
  16. package/dist/index.cjs +29 -0
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.mjs +25 -0
  19. package/dist/intl.d.ts +9 -0
  20. package/dist/navigation.cjs +38 -0
  21. package/dist/navigation.d.ts +2 -0
  22. package/dist/navigation.mjs +39 -0
  23. package/dist/routes.cjs +71 -0
  24. package/dist/routes.d.ts +4 -0
  25. package/dist/routes.mjs +71 -0
  26. package/dist/types.cjs +1 -0
  27. package/dist/types.d.ts +13 -0
  28. package/dist/types.mjs +0 -0
  29. package/dist/ui/[...catchAll]/page.cjs +127 -0
  30. package/dist/ui/[...catchAll]/page.d.ts +13 -0
  31. package/dist/ui/[...catchAll]/page.mjs +88 -0
  32. package/dist/ui/components/app-content.cjs +49 -0
  33. package/dist/ui/components/app-content.d.ts +6 -0
  34. package/dist/ui/components/app-content.mjs +34 -0
  35. package/dist/ui/components/app-header.cjs +55 -0
  36. package/dist/ui/components/app-header.d.ts +6 -0
  37. package/dist/ui/components/app-header.mjs +45 -0
  38. package/dist/ui/components/app-sidebar.cjs +133 -0
  39. package/dist/ui/components/app-sidebar.d.ts +17 -0
  40. package/dist/ui/components/app-sidebar.mjs +142 -0
  41. package/dist/ui/components/app-user.cjs +102 -0
  42. package/dist/ui/components/app-user.d.ts +2 -0
  43. package/dist/ui/components/app-user.mjs +92 -0
  44. package/dist/ui/components/breadcrumb-slot.cjs +35 -0
  45. package/dist/ui/components/breadcrumb-slot.d.ts +2 -0
  46. package/dist/ui/components/breadcrumb-slot.mjs +31 -0
  47. package/dist/ui/components/manager/module-card.cjs +213 -0
  48. package/dist/ui/components/manager/module-card.d.ts +12 -0
  49. package/dist/ui/components/manager/module-card.mjs +197 -0
  50. package/dist/ui/components/manager/module-list.cjs +52 -0
  51. package/dist/ui/components/manager/module-list.d.ts +4 -0
  52. package/dist/ui/components/manager/module-list.mjs +16 -0
  53. package/dist/ui/components/manager/module-upload.cjs +81 -0
  54. package/dist/ui/components/manager/module-upload.d.ts +2 -0
  55. package/dist/ui/components/manager/module-upload.mjs +68 -0
  56. package/dist/ui/components/profile/components.cjs +239 -0
  57. package/dist/ui/components/profile/components.d.ts +8 -0
  58. package/dist/ui/components/profile/components.mjs +219 -0
  59. package/dist/ui/components/profile/link.cjs +25 -0
  60. package/dist/ui/components/profile/link.d.ts +1 -0
  61. package/dist/ui/components/profile/link.mjs +13 -0
  62. package/dist/ui/components/profile/page.cjs +41 -0
  63. package/dist/ui/components/profile/page.d.ts +1 -0
  64. package/dist/ui/components/profile/page.mjs +21 -0
  65. package/dist/ui/components/sidebar-slot.cjs +49 -0
  66. package/dist/ui/components/sidebar-slot.d.ts +2 -0
  67. package/dist/ui/components/sidebar-slot.mjs +33 -0
  68. package/dist/ui/dashboard/page.cjs +31 -0
  69. package/dist/ui/dashboard/page.d.ts +2 -0
  70. package/dist/ui/dashboard/page.mjs +9 -0
  71. package/dist/ui/error.cjs +50 -0
  72. package/dist/ui/error.d.ts +7 -0
  73. package/dist/ui/error.mjs +35 -0
  74. package/dist/ui/layout.cjs +48 -0
  75. package/dist/ui/layout.d.ts +4 -0
  76. package/dist/ui/layout.mjs +35 -0
  77. package/dist/ui/modules/docs/page.cjs +98 -0
  78. package/dist/ui/modules/docs/page.d.ts +6 -0
  79. package/dist/ui/modules/docs/page.mjs +46 -0
  80. package/dist/ui/modules/page.cjs +30 -0
  81. package/dist/ui/modules/page.d.ts +2 -0
  82. package/dist/ui/modules/page.mjs +10 -0
  83. package/dist/ui/page.cjs +18 -0
  84. package/dist/ui/page.d.ts +1 -0
  85. package/dist/ui/page.mjs +9 -0
  86. package/dist/ui/router.cjs +61 -0
  87. package/dist/ui/router.d.ts +5 -0
  88. package/dist/ui/router.mjs +51 -0
  89. package/dist/ui/settings/page.cjs +61 -0
  90. package/dist/ui/settings/page.d.ts +2 -0
  91. package/dist/ui/settings/page.mjs +22 -0
  92. package/dist/ui/settings-page.cjs +76 -0
  93. package/dist/ui/settings-page.d.ts +2 -0
  94. package/dist/ui/settings-page.mjs +57 -0
  95. package/locales/en/global.json +80 -0
  96. package/manifest.json +11 -0
  97. package/package.json +67 -0
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ "use client";
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ module.exports = BreadcrumbSlot;
8
+ var _intl = require("@arch-cadre/intl");
9
+ var _breadcrumb = require("@arch-cadre/ui/components/breadcrumb");
10
+ var _tooltip = require("@arch-cadre/ui/components/tooltip");
11
+ var _image = _interopRequireDefault(require("next/image"));
12
+ var _link = _interopRequireDefault(require("next/link"));
13
+ var React = _interopRequireWildcard(require("react"));
14
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
15
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
+ function BreadcrumbSlot() {
18
+ const {
19
+ t
20
+ } = (0, _intl.useTranslation)();
21
+ return /* @__PURE__ */React.createElement(_breadcrumb.Breadcrumb, {
22
+ className: "hidden sm:block"
23
+ }, /* @__PURE__ */React.createElement(_breadcrumb.BreadcrumbList, null, /* @__PURE__ */React.createElement(_breadcrumb.BreadcrumbItem, null, /* @__PURE__ */React.createElement(_tooltip.Tooltip, null, /* @__PURE__ */React.createElement(_tooltip.TooltipTrigger, {
24
+ asChild: true
25
+ }, /* @__PURE__ */React.createElement(_link.default, {
26
+ href: "/kryo"
27
+ }, /* @__PURE__ */React.createElement(_image.default, {
28
+ width: 16,
29
+ height: 16,
30
+ src: "/favicon.svg",
31
+ alt: "logo",
32
+ className: "size-4",
33
+ "aria-hidden": true
34
+ }))), /* @__PURE__ */React.createElement(_tooltip.TooltipContent, null, /* @__PURE__ */React.createElement("p", null, t("Back to Dashboard"))))), /* @__PURE__ */React.createElement(_breadcrumb.BreadcrumbSeparator, null, "\u2022"), /* @__PURE__ */React.createElement(_breadcrumb.BreadcrumbItem, null, /* @__PURE__ */React.createElement(_breadcrumb.BreadcrumbPage, null, t("Dashboard")))));
35
+ }
@@ -0,0 +1,2 @@
1
+ import * as React from "react";
2
+ export default function BreadcrumbSlot(): React.JSX.Element;
@@ -0,0 +1,31 @@
1
+ "use client";
2
+ import { useTranslation } from "@arch-cadre/intl";
3
+ import {
4
+ Breadcrumb,
5
+ BreadcrumbItem,
6
+ BreadcrumbList,
7
+ BreadcrumbPage,
8
+ BreadcrumbSeparator
9
+ } from "@arch-cadre/ui/components/breadcrumb";
10
+ import {
11
+ Tooltip,
12
+ TooltipContent,
13
+ TooltipTrigger
14
+ } from "@arch-cadre/ui/components/tooltip";
15
+ import Image from "next/image";
16
+ import Link from "next/link";
17
+ import * as React from "react";
18
+ export default function BreadcrumbSlot() {
19
+ const { t } = useTranslation();
20
+ return /* @__PURE__ */ React.createElement(Breadcrumb, { className: "hidden sm:block" }, /* @__PURE__ */ React.createElement(BreadcrumbList, null, /* @__PURE__ */ React.createElement(BreadcrumbItem, null, /* @__PURE__ */ React.createElement(Tooltip, null, /* @__PURE__ */ React.createElement(TooltipTrigger, { asChild: true }, /* @__PURE__ */ React.createElement(Link, { href: "/kryo" }, /* @__PURE__ */ React.createElement(
21
+ Image,
22
+ {
23
+ width: 16,
24
+ height: 16,
25
+ src: "/favicon.svg",
26
+ alt: "logo",
27
+ className: "size-4",
28
+ "aria-hidden": true
29
+ }
30
+ ))), /* @__PURE__ */ React.createElement(TooltipContent, null, /* @__PURE__ */ React.createElement("p", null, t("Back to Dashboard"))))), /* @__PURE__ */ React.createElement(BreadcrumbSeparator, null, "\u2022"), /* @__PURE__ */ React.createElement(BreadcrumbItem, null, /* @__PURE__ */ React.createElement(BreadcrumbPage, null, t("Dashboard")))));
31
+ }
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ "use client";
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.ModuleCard = ModuleCard;
8
+ var _core = require("@arch-cadre/core");
9
+ var _intl = require("@arch-cadre/intl");
10
+ var _badge = require("@arch-cadre/ui/components/badge");
11
+ var _button = require("@arch-cadre/ui/components/button");
12
+ var _card = require("@arch-cadre/ui/components/card");
13
+ var _switch = require("@arch-cadre/ui/components/switch");
14
+ var _loader = require("@arch-cadre/ui/shared/loader");
15
+ var _lucideReact = require("lucide-react");
16
+ var _link = _interopRequireDefault(require("next/link"));
17
+ var _navigation = require("next/navigation");
18
+ var _react = _interopRequireWildcard(require("react"));
19
+ var React = _react;
20
+ var _sonner = require("sonner");
21
+ var _manager = require("../../../actions/manager.cjs");
22
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
23
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
24
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
25
+ function ModuleCard({
26
+ module
27
+ }) {
28
+ const router = (0, _navigation.useRouter)();
29
+ const {
30
+ t
31
+ } = (0, _intl.useTranslation)();
32
+ const [isEnabled, setIsEnabled] = (0, _react.useState)(module.enabled);
33
+ const [isProcessing, setIsProcessing] = (0, _react.useState)(!!module.lastStep);
34
+ const [localStep, setLocalStep] = (0, _react.useState)(module.lastStep || null);
35
+ const pollerRef = (0, _react.useRef)(null);
36
+ const stopPolling = (0, _react.useCallback)(() => {
37
+ if (pollerRef.current) {
38
+ clearInterval(pollerRef.current);
39
+ pollerRef.current = null;
40
+ }
41
+ }, []);
42
+ const startPolling = (0, _react.useCallback)(() => {
43
+ if (pollerRef.current) return;
44
+ pollerRef.current = setInterval(async () => {
45
+ try {
46
+ const res = await fetch(`/api/system/modules/${module.id}/status`);
47
+ const status = await res.json();
48
+ if (status.lastStep) {
49
+ setLocalStep(status.lastStep);
50
+ }
51
+ if (!status.lastStep) {
52
+ setIsProcessing(false);
53
+ setLocalStep(null);
54
+ stopPolling();
55
+ router.refresh();
56
+ } else if (status.lastStep.toLowerCase().includes("error")) {
57
+ setIsProcessing(false);
58
+ stopPolling();
59
+ }
60
+ } catch (e) {
61
+ console.error("Polling error", e);
62
+ }
63
+ }, 1e3);
64
+ }, [module.id, router, stopPolling]);
65
+ (0, _react.useEffect)(() => {
66
+ const eventType = "module:status:check";
67
+ const subscriberId = `card-${module.id}`;
68
+ _core.eventBus.subscribe(eventType, subscriberId, event => {
69
+ const {
70
+ triggerSource,
71
+ dependencies,
72
+ action
73
+ } = event.payload;
74
+ if (triggerSource === module.id || module.system) return;
75
+ let shouldCheck = false;
76
+ if (action === "enable") {
77
+ if (dependencies.includes(module.id)) {
78
+ shouldCheck = true;
79
+ }
80
+ } else if (action === "disable") {
81
+ if (module.dependencies?.includes(triggerSource)) {
82
+ shouldCheck = true;
83
+ }
84
+ if (dependencies.includes(module.id)) {
85
+ shouldCheck = true;
86
+ }
87
+ }
88
+ if (shouldCheck && !isProcessing) {
89
+ setIsProcessing(true);
90
+ setLocalStep(t("Waiting..."));
91
+ startPolling();
92
+ }
93
+ });
94
+ return () => _core.eventBus.unsubscribe(eventType, subscriberId);
95
+ }, [module.id, module.dependencies, isProcessing, module.system, startPolling, t]);
96
+ (0, _react.useEffect)(() => {
97
+ if (module.lastStep) {
98
+ setIsProcessing(true);
99
+ setLocalStep(module.lastStep);
100
+ startPolling();
101
+ }
102
+ return () => stopPolling();
103
+ }, [module.lastStep, startPolling, stopPolling]);
104
+ (0, _react.useEffect)(() => {
105
+ setIsEnabled(module.enabled);
106
+ }, [module.enabled]);
107
+ const handleToggle = async checked => {
108
+ setIsProcessing(true);
109
+ setLocalStep(t("Starting..."));
110
+ setIsEnabled(checked);
111
+ _core.eventBus.publish("module:status:check", {
112
+ triggerSource: module.id,
113
+ dependencies: module.dependencies || [],
114
+ action: checked ? "enable" : "disable"
115
+ }, `card-${module.id}`);
116
+ try {
117
+ await (0, _manager.toggleModuleAction)(module.id, checked);
118
+ startPolling();
119
+ } catch (_error) {
120
+ setIsEnabled(!checked);
121
+ setIsProcessing(false);
122
+ setLocalStep(null);
123
+ _sonner.toast.error(t("error_occurred"));
124
+ }
125
+ };
126
+ return /* @__PURE__ */React.createElement(_card.Card, {
127
+ className: `relative overflow-hidden transition-all duration-300 ${!isEnabled && !module.system ? "opacity-75 shadow-none border-dashed" : "shadow-md"}`
128
+ }, isProcessing && /* @__PURE__ */React.createElement("div", {
129
+ className: "absolute top-0 left-0 w-full h-1 bg-primary/20 overflow-hidden"
130
+ }, /* @__PURE__ */React.createElement("div", {
131
+ className: `h-full bg-primary ${localStep?.startsWith("Waiting") ? "animate-pulse opacity-50" : "animate-progress-fast"}`,
132
+ style: {
133
+ width: localStep?.startsWith("Waiting") ? "100%" : "40%"
134
+ }
135
+ })), /* @__PURE__ */React.createElement(_card.CardHeader, {
136
+ className: "flex flex-row items-center justify-between space-y-0 pb-2"
137
+ }, /* @__PURE__ */React.createElement(_card.CardTitle, {
138
+ className: "text-base font-medium flex items-center gap-2"
139
+ }, module.name, module.system && /* @__PURE__ */React.createElement(_lucideReact.ShieldCheck, {
140
+ className: "size-4 text-primary"
141
+ })), /* @__PURE__ */React.createElement("div", {
142
+ className: "flex items-center gap-2"
143
+ }, module.hasDocs && /* @__PURE__ */React.createElement(_button.Button, {
144
+ asChild: true,
145
+ variant: "ghost",
146
+ size: "icon",
147
+ className: "h-8 w-8",
148
+ title: t("View documentation")
149
+ }, /* @__PURE__ */React.createElement(_link.default, {
150
+ href: `/kryo/modules/docs/${module.id}`
151
+ }, /* @__PURE__ */React.createElement(_lucideReact.FileText, {
152
+ className: "size-4"
153
+ }))), !module.system && /* @__PURE__ */React.createElement(_switch.Switch, {
154
+ checked: isEnabled,
155
+ onCheckedChange: handleToggle,
156
+ disabled: isProcessing
157
+ }))), /* @__PURE__ */React.createElement(_card.CardContent, null, /* @__PURE__ */React.createElement("div", {
158
+ className: "flex items-center gap-2 mb-4"
159
+ }, /* @__PURE__ */React.createElement(_badge.Badge, {
160
+ variant: isEnabled || module.system ? "default" : "secondary"
161
+ }, isProcessing ? /* @__PURE__ */React.createElement("span", {
162
+ className: "flex items-center gap-1"
163
+ }, /* @__PURE__ */React.createElement(_loader.Loader, {
164
+ variant: isEnabled || module.system ? "dark" : "default",
165
+ className: "size-3"
166
+ }), localStep?.startsWith("Waiting") ? t("Please wait...") : t("Working...")) : isEnabled || module.system ? t("Enabled") : t("Disabled")), module.installed && /* @__PURE__ */React.createElement(_badge.Badge, {
167
+ variant: "outline",
168
+ className: "text-[10px] h-5 font-mono"
169
+ }, t("Installed")), module.isNpm && /* @__PURE__ */React.createElement(_badge.Badge, {
170
+ variant: "secondary",
171
+ className: "text-[10px] h-5 font-mono bg-blue-500/10 text-blue-600 border-blue-500/20"
172
+ }, "NPM"), /* @__PURE__ */React.createElement("span", {
173
+ className: "text-xs text-muted-foreground ml-auto"
174
+ }, "v", module.version)), isProcessing || localStep ? /* @__PURE__ */React.createElement("div", {
175
+ className: `p-2 rounded-lg border text-[11px] font-mono mb-2 flex items-center gap-2 ${localStep?.toLowerCase().includes("error") ? "bg-destructive/10 text-destructive border-destructive/20" : localStep?.startsWith("Waiting") ? "bg-amber-500/10 text-amber-600 border-amber-500/20" : "bg-muted/50 text-muted-foreground"}`
176
+ }, localStep?.toLowerCase().includes("error") ? /* @__PURE__ */React.createElement(_lucideReact.AlertCircle, {
177
+ className: "size-3"
178
+ }) : localStep?.startsWith("Waiting") ? /* @__PURE__ */React.createElement(_loader.Loader, {
179
+ className: "size-3 animate-spin opacity-50"
180
+ }) : /* @__PURE__ */React.createElement(_loader.Loader, {
181
+ className: "size-3 animate-spin"
182
+ }), /* @__PURE__ */React.createElement("span", {
183
+ className: "truncate"
184
+ }, localStep || t("Processing"))) : /* @__PURE__ */React.createElement("div", {
185
+ className: "space-y-3"
186
+ }, /* @__PURE__ */React.createElement("p", {
187
+ className: "text-sm text-muted-foreground line-clamp-2 h-[40px]"
188
+ }, t(module.description)), /* @__PURE__ */React.createElement("div", {
189
+ className: "flex flex-wrap gap-y-2 gap-x-4 pt-2 border-t border-muted/50"
190
+ }, (!module.extends || module.extends.length === 0) && (!module.dependencies || module.dependencies.length === 0) ? /* @__PURE__ */React.createElement("div", {
191
+ className: "flex items-center gap-1.5"
192
+ }, /* @__PURE__ */React.createElement("span", {
193
+ className: "text-[10px] font-black uppercase tracking-tight text-muted-foreground/40 italic"
194
+ }, t("No dependencies"))) : /* @__PURE__ */React.createElement(React.Fragment, null, module.extends && module.extends.length > 0 && /* @__PURE__ */React.createElement("div", {
195
+ className: "flex items-center gap-1.5"
196
+ }, /* @__PURE__ */React.createElement("span", {
197
+ className: "text-[10px] font-black uppercase tracking-tight text-primary/70"
198
+ }, t("Extends")), /* @__PURE__ */React.createElement("div", {
199
+ className: "flex gap-1"
200
+ }, module.extends.map(ext => /* @__PURE__ */React.createElement("span", {
201
+ key: ext,
202
+ className: "text-[10px] font-mono bg-primary/5 text-primary px-1 rounded border border-primary/10"
203
+ }, ext)))), module.dependencies && module.dependencies.length > 0 && /* @__PURE__ */React.createElement("div", {
204
+ className: "flex items-center gap-1.5"
205
+ }, /* @__PURE__ */React.createElement("span", {
206
+ className: "text-[10px] font-black uppercase tracking-tight text-muted-foreground"
207
+ }, t("Requires")), /* @__PURE__ */React.createElement("div", {
208
+ className: "flex gap-1"
209
+ }, module.dependencies.map(dep => /* @__PURE__ */React.createElement("span", {
210
+ key: dep,
211
+ className: "text-[10px] font-mono bg-muted text-muted-foreground px-1 rounded border"
212
+ }, dep)))))))));
213
+ }
@@ -0,0 +1,12 @@
1
+ import type { ModuleManifest } from "@arch-cadre/modules";
2
+ import * as React from "react";
3
+ interface ModuleCardProps {
4
+ module: ModuleManifest & {
5
+ installed?: boolean;
6
+ hasDocs?: boolean;
7
+ lastStep?: string | null;
8
+ isNpm?: boolean;
9
+ };
10
+ }
11
+ export declare function ModuleCard({ module }: ModuleCardProps): React.JSX.Element;
12
+ export {};
@@ -0,0 +1,197 @@
1
+ "use client";
2
+ import { eventBus } from "@arch-cadre/core";
3
+ import { useTranslation } from "@arch-cadre/intl";
4
+ import { Badge } from "@arch-cadre/ui/components/badge";
5
+ import { Button } from "@arch-cadre/ui/components/button";
6
+ import {
7
+ Card,
8
+ CardContent,
9
+ CardHeader,
10
+ CardTitle
11
+ } from "@arch-cadre/ui/components/card";
12
+ import { Switch } from "@arch-cadre/ui/components/switch";
13
+ import { Loader } from "@arch-cadre/ui/shared/loader";
14
+ import { AlertCircle, FileText, ShieldCheck } from "lucide-react";
15
+ import Link from "next/link";
16
+ import { useRouter } from "next/navigation";
17
+ import * as React from "react";
18
+ import { useCallback, useEffect, useRef, useState } from "react";
19
+ import { toast } from "sonner";
20
+ import { toggleModuleAction } from "../../../actions/manager.mjs";
21
+ export function ModuleCard({ module }) {
22
+ const router = useRouter();
23
+ const { t } = useTranslation();
24
+ const [isEnabled, setIsEnabled] = useState(module.enabled);
25
+ const [isProcessing, setIsProcessing] = useState(!!module.lastStep);
26
+ const [localStep, setLocalStep] = useState(
27
+ module.lastStep || null
28
+ );
29
+ const pollerRef = useRef(null);
30
+ const stopPolling = useCallback(() => {
31
+ if (pollerRef.current) {
32
+ clearInterval(pollerRef.current);
33
+ pollerRef.current = null;
34
+ }
35
+ }, []);
36
+ const startPolling = useCallback(() => {
37
+ if (pollerRef.current) return;
38
+ pollerRef.current = setInterval(async () => {
39
+ try {
40
+ const res = await fetch(`/api/system/modules/${module.id}/status`);
41
+ const status = await res.json();
42
+ if (status.lastStep) {
43
+ setLocalStep(status.lastStep);
44
+ }
45
+ if (!status.lastStep) {
46
+ setIsProcessing(false);
47
+ setLocalStep(null);
48
+ stopPolling();
49
+ router.refresh();
50
+ } else if (status.lastStep.toLowerCase().includes("error")) {
51
+ setIsProcessing(false);
52
+ stopPolling();
53
+ }
54
+ } catch (e) {
55
+ console.error("Polling error", e);
56
+ }
57
+ }, 1e3);
58
+ }, [module.id, router, stopPolling]);
59
+ useEffect(() => {
60
+ const eventType = "module:status:check";
61
+ const subscriberId = `card-${module.id}`;
62
+ eventBus.subscribe(
63
+ eventType,
64
+ subscriberId,
65
+ (event) => {
66
+ const { triggerSource, dependencies, action } = event.payload;
67
+ if (triggerSource === module.id || module.system) return;
68
+ let shouldCheck = false;
69
+ if (action === "enable") {
70
+ if (dependencies.includes(module.id)) {
71
+ shouldCheck = true;
72
+ }
73
+ } else if (action === "disable") {
74
+ if (module.dependencies?.includes(triggerSource)) {
75
+ shouldCheck = true;
76
+ }
77
+ if (dependencies.includes(module.id)) {
78
+ shouldCheck = true;
79
+ }
80
+ }
81
+ if (shouldCheck && !isProcessing) {
82
+ setIsProcessing(true);
83
+ setLocalStep(t("Waiting..."));
84
+ startPolling();
85
+ }
86
+ }
87
+ );
88
+ return () => eventBus.unsubscribe(eventType, subscriberId);
89
+ }, [
90
+ module.id,
91
+ module.dependencies,
92
+ isProcessing,
93
+ module.system,
94
+ startPolling,
95
+ t
96
+ ]);
97
+ useEffect(() => {
98
+ if (module.lastStep) {
99
+ setIsProcessing(true);
100
+ setLocalStep(module.lastStep);
101
+ startPolling();
102
+ }
103
+ return () => stopPolling();
104
+ }, [module.lastStep, startPolling, stopPolling]);
105
+ useEffect(() => {
106
+ setIsEnabled(module.enabled);
107
+ }, [module.enabled]);
108
+ const handleToggle = async (checked) => {
109
+ setIsProcessing(true);
110
+ setLocalStep(t("Starting..."));
111
+ setIsEnabled(checked);
112
+ eventBus.publish(
113
+ "module:status:check",
114
+ {
115
+ triggerSource: module.id,
116
+ dependencies: module.dependencies || [],
117
+ action: checked ? "enable" : "disable"
118
+ },
119
+ `card-${module.id}`
120
+ );
121
+ try {
122
+ await toggleModuleAction(module.id, checked);
123
+ startPolling();
124
+ } catch (_error) {
125
+ setIsEnabled(!checked);
126
+ setIsProcessing(false);
127
+ setLocalStep(null);
128
+ toast.error(t("error_occurred"));
129
+ }
130
+ };
131
+ return /* @__PURE__ */ React.createElement(
132
+ Card,
133
+ {
134
+ className: `relative overflow-hidden transition-all duration-300 ${!isEnabled && !module.system ? "opacity-75 shadow-none border-dashed" : "shadow-md"}`
135
+ },
136
+ isProcessing && /* @__PURE__ */ React.createElement("div", { className: "absolute top-0 left-0 w-full h-1 bg-primary/20 overflow-hidden" }, /* @__PURE__ */ React.createElement(
137
+ "div",
138
+ {
139
+ className: `h-full bg-primary ${localStep?.startsWith("Waiting") ? "animate-pulse opacity-50" : "animate-progress-fast"}`,
140
+ style: { width: localStep?.startsWith("Waiting") ? "100%" : "40%" }
141
+ }
142
+ )),
143
+ /* @__PURE__ */ React.createElement(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2" }, /* @__PURE__ */ React.createElement(CardTitle, { className: "text-base font-medium flex items-center gap-2" }, module.name, module.system && /* @__PURE__ */ React.createElement(ShieldCheck, { className: "size-4 text-primary" })), /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, module.hasDocs && /* @__PURE__ */ React.createElement(
144
+ Button,
145
+ {
146
+ asChild: true,
147
+ variant: "ghost",
148
+ size: "icon",
149
+ className: "h-8 w-8",
150
+ title: t("View documentation")
151
+ },
152
+ /* @__PURE__ */ React.createElement(Link, { href: `/kryo/modules/docs/${module.id}` }, /* @__PURE__ */ React.createElement(FileText, { className: "size-4" }))
153
+ ), !module.system && /* @__PURE__ */ React.createElement(
154
+ Switch,
155
+ {
156
+ checked: isEnabled,
157
+ onCheckedChange: handleToggle,
158
+ disabled: isProcessing
159
+ }
160
+ ))),
161
+ /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 mb-4" }, /* @__PURE__ */ React.createElement(Badge, { variant: isEnabled || module.system ? "default" : "secondary" }, isProcessing ? /* @__PURE__ */ React.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ React.createElement(
162
+ Loader,
163
+ {
164
+ variant: isEnabled || module.system ? "dark" : "default",
165
+ className: "size-3"
166
+ }
167
+ ), localStep?.startsWith("Waiting") ? t("Please wait...") : t("Working...")) : isEnabled || module.system ? t("Enabled") : t("Disabled")), module.installed && /* @__PURE__ */ React.createElement(Badge, { variant: "outline", className: "text-[10px] h-5 font-mono" }, t("Installed")), module.isNpm && /* @__PURE__ */ React.createElement(
168
+ Badge,
169
+ {
170
+ variant: "secondary",
171
+ className: "text-[10px] h-5 font-mono bg-blue-500/10 text-blue-600 border-blue-500/20"
172
+ },
173
+ "NPM"
174
+ ), /* @__PURE__ */ React.createElement("span", { className: "text-xs text-muted-foreground ml-auto" }, "v", module.version)), isProcessing || localStep ? /* @__PURE__ */ React.createElement(
175
+ "div",
176
+ {
177
+ className: `p-2 rounded-lg border text-[11px] font-mono mb-2 flex items-center gap-2 ${localStep?.toLowerCase().includes("error") ? "bg-destructive/10 text-destructive border-destructive/20" : localStep?.startsWith("Waiting") ? "bg-amber-500/10 text-amber-600 border-amber-500/20" : "bg-muted/50 text-muted-foreground"}`
178
+ },
179
+ localStep?.toLowerCase().includes("error") ? /* @__PURE__ */ React.createElement(AlertCircle, { className: "size-3" }) : localStep?.startsWith("Waiting") ? /* @__PURE__ */ React.createElement(Loader, { className: "size-3 animate-spin opacity-50" }) : /* @__PURE__ */ React.createElement(Loader, { className: "size-3 animate-spin" }),
180
+ /* @__PURE__ */ React.createElement("span", { className: "truncate" }, localStep || t("Processing"))
181
+ ) : /* @__PURE__ */ React.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React.createElement("p", { className: "text-sm text-muted-foreground line-clamp-2 h-[40px]" }, t(module.description)), /* @__PURE__ */ React.createElement("div", { className: "flex flex-wrap gap-y-2 gap-x-4 pt-2 border-t border-muted/50" }, (!module.extends || module.extends.length === 0) && (!module.dependencies || module.dependencies.length === 0) ? /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React.createElement("span", { className: "text-[10px] font-black uppercase tracking-tight text-muted-foreground/40 italic" }, t("No dependencies"))) : /* @__PURE__ */ React.createElement(React.Fragment, null, module.extends && module.extends.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React.createElement("span", { className: "text-[10px] font-black uppercase tracking-tight text-primary/70" }, t("Extends")), /* @__PURE__ */ React.createElement("div", { className: "flex gap-1" }, module.extends.map((ext) => /* @__PURE__ */ React.createElement(
182
+ "span",
183
+ {
184
+ key: ext,
185
+ className: "text-[10px] font-mono bg-primary/5 text-primary px-1 rounded border border-primary/10"
186
+ },
187
+ ext
188
+ )))), module.dependencies && module.dependencies.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React.createElement("span", { className: "text-[10px] font-black uppercase tracking-tight text-muted-foreground" }, t("Requires")), /* @__PURE__ */ React.createElement("div", { className: "flex gap-1" }, module.dependencies.map((dep) => /* @__PURE__ */ React.createElement(
189
+ "span",
190
+ {
191
+ key: dep,
192
+ className: "text-[10px] font-mono bg-muted text-muted-foreground px-1 rounded border"
193
+ },
194
+ dep
195
+ ))))))))
196
+ );
197
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ "use client";
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.ModuleMarketplaceList = ModuleMarketplaceList;
8
+ var _intl = require("@arch-cadre/intl");
9
+ var _separator = require("@arch-cadre/ui/components/separator");
10
+ var React = _interopRequireWildcard(require("react"));
11
+ var _moduleCard = require("./module-card.cjs");
12
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
13
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
14
+ function ModuleMarketplaceList({
15
+ initialModules
16
+ }) {
17
+ const {
18
+ t
19
+ } = (0, _intl.useTranslation)();
20
+ const sortedModules = [...initialModules].sort((a, b) => a.name.localeCompare(b.name));
21
+ const coreModules = sortedModules.filter(m => m.system);
22
+ const publicModules = sortedModules.filter(m => !m.system);
23
+ return /* @__PURE__ */React.createElement("div", {
24
+ className: "space-y-10"
25
+ }, publicModules.length > 0 && /* @__PURE__ */React.createElement("div", {
26
+ className: "space-y-6"
27
+ }, /* @__PURE__ */React.createElement("div", {
28
+ className: "flex items-center gap-4"
29
+ }, /* @__PURE__ */React.createElement("h3", {
30
+ className: "text-sm font-bold uppercase tracking-widest text-muted-foreground shrink-0"
31
+ }, t("Public Modules")), /* @__PURE__ */React.createElement(_separator.Separator, {
32
+ className: "flex-1"
33
+ })), /* @__PURE__ */React.createElement("div", {
34
+ className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3"
35
+ }, publicModules.map(module => /* @__PURE__ */React.createElement(_moduleCard.ModuleCard, {
36
+ key: module.id,
37
+ module
38
+ })))), coreModules.length > 0 && /* @__PURE__ */React.createElement("div", {
39
+ className: "space-y-6"
40
+ }, /* @__PURE__ */React.createElement("div", {
41
+ className: "flex items-center gap-4"
42
+ }, /* @__PURE__ */React.createElement("h3", {
43
+ className: "text-sm font-bold uppercase tracking-widest text-primary shrink-0"
44
+ }, t("Core Modules")), /* @__PURE__ */React.createElement(_separator.Separator, {
45
+ className: "flex-1"
46
+ })), /* @__PURE__ */React.createElement("div", {
47
+ className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3"
48
+ }, coreModules.map(module => /* @__PURE__ */React.createElement(_moduleCard.ModuleCard, {
49
+ key: module.id,
50
+ module
51
+ })))));
52
+ }
@@ -0,0 +1,4 @@
1
+ import * as React from "react";
2
+ export declare function ModuleMarketplaceList({ initialModules, }: {
3
+ initialModules: any[];
4
+ }): React.JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { useTranslation } from "@arch-cadre/intl";
3
+ import { Separator } from "@arch-cadre/ui/components/separator";
4
+ import * as React from "react";
5
+ import { ModuleCard } from "./module-card.mjs";
6
+ export function ModuleMarketplaceList({
7
+ initialModules
8
+ }) {
9
+ const { t } = useTranslation();
10
+ const sortedModules = [...initialModules].sort(
11
+ (a, b) => a.name.localeCompare(b.name)
12
+ );
13
+ const coreModules = sortedModules.filter((m) => m.system);
14
+ const publicModules = sortedModules.filter((m) => !m.system);
15
+ return /* @__PURE__ */ React.createElement("div", { className: "space-y-10" }, publicModules.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React.createElement("h3", { className: "text-sm font-bold uppercase tracking-widest text-muted-foreground shrink-0" }, t("Public Modules")), /* @__PURE__ */ React.createElement(Separator, { className: "flex-1" })), /* @__PURE__ */ React.createElement("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3" }, publicModules.map((module) => /* @__PURE__ */ React.createElement(ModuleCard, { key: module.id, module })))), coreModules.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React.createElement("h3", { className: "text-sm font-bold uppercase tracking-widest text-primary shrink-0" }, t("Core Modules")), /* @__PURE__ */ React.createElement(Separator, { className: "flex-1" })), /* @__PURE__ */ React.createElement("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3" }, coreModules.map((module) => /* @__PURE__ */ React.createElement(ModuleCard, { key: module.id, module })))));
16
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ "use client";
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.ModuleUpload = ModuleUpload;
8
+ var _intl = require("@arch-cadre/intl");
9
+ var _button = require("@arch-cadre/ui/components/button");
10
+ var _lucideReact = require("lucide-react");
11
+ var _react = _interopRequireWildcard(require("react"));
12
+ var React = _react;
13
+ var _sonner = require("sonner");
14
+ var _manager = require("../../../actions/manager.cjs");
15
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
+ function ModuleUpload() {
18
+ const [isUploading, setIsUploading] = (0, _react.useState)(false);
19
+ const [canWrite, setCanWrite] = (0, _react.useState)(null);
20
+ const fileInputRef = (0, _react.useRef)(null);
21
+ const {
22
+ t
23
+ } = (0, _intl.useTranslation)();
24
+ (0, _react.useEffect)(() => {
25
+ (0, _manager.checkDiskWriteAccess)().then(res => setCanWrite(res.canWrite));
26
+ }, []);
27
+ const handleUpload = async e => {
28
+ const file = e.target.files?.[0];
29
+ if (!file) return;
30
+ if (!file.name.endsWith(".zip")) {
31
+ _sonner.toast.error(t("Invalid file"));
32
+ return;
33
+ }
34
+ const formData = new FormData();
35
+ formData.append("file", file);
36
+ setIsUploading(true);
37
+ const id = _sonner.toast.loading(t("Uploading..."));
38
+ try {
39
+ const result = await (0, _manager.uploadModuleAction)(formData);
40
+ if (result.success) {
41
+ _sonner.toast.success(t("Upload successful"), {
42
+ id
43
+ });
44
+ if (fileInputRef.current) fileInputRef.current.value = "";
45
+ } else {
46
+ _sonner.toast.error(result.error || t("Upload error"), {
47
+ id
48
+ });
49
+ }
50
+ } catch (_error) {
51
+ _sonner.toast.error(t("error_occurred"), {
52
+ id
53
+ });
54
+ } finally {
55
+ setIsUploading(false);
56
+ }
57
+ };
58
+ return /* @__PURE__ */React.createElement("div", {
59
+ className: "flex items-center gap-4"
60
+ }, /* @__PURE__ */React.createElement("input", {
61
+ type: "file",
62
+ accept: ".zip",
63
+ className: "hidden",
64
+ ref: fileInputRef,
65
+ onChange: handleUpload,
66
+ disabled: isUploading
67
+ }), /* @__PURE__ */React.createElement(_button.Button, {
68
+ onClick: () => fileInputRef.current?.click(),
69
+ disabled: isUploading || canWrite === false,
70
+ variant: "outline",
71
+ size: "sm",
72
+ className: "gap-2 w-full sm:w-auto",
73
+ title: canWrite === false ? t("No write access") : void 0
74
+ }, isUploading ? /* @__PURE__ */React.createElement(_lucideReact.Loader2, {
75
+ className: "size-4 animate-spin"
76
+ }) : canWrite === false ? /* @__PURE__ */React.createElement(_lucideReact.Lock, {
77
+ className: "size-4 text-destructive"
78
+ }) : /* @__PURE__ */React.createElement(_lucideReact.Upload, {
79
+ className: "size-4"
80
+ }), canWrite === false ? t("Upload disabled") : t("Upload module")));
81
+ }