@gbdx/devis 1.0.1 → 1.0.2
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.
|
@@ -29115,6 +29115,75 @@ async function fetchCaddyRouteCount() {
|
|
|
29115
29115
|
return null;
|
|
29116
29116
|
}
|
|
29117
29117
|
}
|
|
29118
|
+
function collectCaddyHosts(match) {
|
|
29119
|
+
if (!Array.isArray(match)) return [];
|
|
29120
|
+
const hosts = [];
|
|
29121
|
+
for (const m of match) {
|
|
29122
|
+
const host = m == null ? void 0 : m.host;
|
|
29123
|
+
if (Array.isArray(host)) {
|
|
29124
|
+
for (const h of host) if (typeof h === "string") hosts.push(h);
|
|
29125
|
+
}
|
|
29126
|
+
}
|
|
29127
|
+
return [...new Set(hosts)];
|
|
29128
|
+
}
|
|
29129
|
+
function collectCaddyHandlers(handle) {
|
|
29130
|
+
const upstreams = [];
|
|
29131
|
+
const handlers = [];
|
|
29132
|
+
const walk = (arr) => {
|
|
29133
|
+
if (!Array.isArray(arr)) return;
|
|
29134
|
+
for (const h of arr) {
|
|
29135
|
+
if (!h || typeof h !== "object") continue;
|
|
29136
|
+
const obj = h;
|
|
29137
|
+
if (typeof obj.handler === "string") handlers.push(obj.handler);
|
|
29138
|
+
if (Array.isArray(obj.upstreams)) {
|
|
29139
|
+
for (const u of obj.upstreams) {
|
|
29140
|
+
const dial = u == null ? void 0 : u.dial;
|
|
29141
|
+
if (typeof dial === "string") upstreams.push(dial);
|
|
29142
|
+
}
|
|
29143
|
+
}
|
|
29144
|
+
if (Array.isArray(obj.routes)) {
|
|
29145
|
+
for (const r2 of obj.routes) walk(r2 == null ? void 0 : r2.handle);
|
|
29146
|
+
}
|
|
29147
|
+
}
|
|
29148
|
+
};
|
|
29149
|
+
walk(handle);
|
|
29150
|
+
return { upstreams: [...new Set(upstreams)], handlers: [...new Set(handlers)] };
|
|
29151
|
+
}
|
|
29152
|
+
function parseCaddyRoute(route) {
|
|
29153
|
+
const r2 = route ?? {};
|
|
29154
|
+
const id = typeof r2["@id"] === "string" ? r2["@id"] : null;
|
|
29155
|
+
let slug = null;
|
|
29156
|
+
let appName = null;
|
|
29157
|
+
if (id) {
|
|
29158
|
+
const parts = id.split(":");
|
|
29159
|
+
if (parts.length >= 3 && parts[1] === "route") {
|
|
29160
|
+
slug = parts[0];
|
|
29161
|
+
appName = parts.slice(2).join(":");
|
|
29162
|
+
}
|
|
29163
|
+
}
|
|
29164
|
+
const hosts = collectCaddyHosts(r2.match);
|
|
29165
|
+
const { upstreams, handlers } = collectCaddyHandlers(r2.handle);
|
|
29166
|
+
return { id, slug, appName, hosts, upstreams, handlers };
|
|
29167
|
+
}
|
|
29168
|
+
async function fetchCaddyRoutes() {
|
|
29169
|
+
var _a, _b;
|
|
29170
|
+
const body2 = await caddyGet("/config/");
|
|
29171
|
+
if (!body2) return [];
|
|
29172
|
+
let cfg;
|
|
29173
|
+
try {
|
|
29174
|
+
cfg = JSON.parse(body2);
|
|
29175
|
+
} catch {
|
|
29176
|
+
return [];
|
|
29177
|
+
}
|
|
29178
|
+
const servers = ((_b = (_a = cfg.apps) == null ? void 0 : _a.http) == null ? void 0 : _b.servers) ?? {};
|
|
29179
|
+
const out = [];
|
|
29180
|
+
for (const srv of Object.values(servers)) {
|
|
29181
|
+
if (Array.isArray(srv == null ? void 0 : srv.routes)) {
|
|
29182
|
+
for (const route of srv.routes) out.push(parseCaddyRoute(route));
|
|
29183
|
+
}
|
|
29184
|
+
}
|
|
29185
|
+
return out;
|
|
29186
|
+
}
|
|
29118
29187
|
function caddyPaths() {
|
|
29119
29188
|
const home = getGlobalContext().homeDir;
|
|
29120
29189
|
return {
|
|
@@ -29355,6 +29424,75 @@ function statusLabel(info) {
|
|
|
29355
29424
|
}
|
|
29356
29425
|
function CaddyView({ caddy, onLogs, onChanged, openLogKey }) {
|
|
29357
29426
|
var _a, _b;
|
|
29427
|
+
const [routesOpen, setRoutesOpen] = reactExports.useState(false);
|
|
29428
|
+
const [routes, setRoutes] = reactExports.useState(null);
|
|
29429
|
+
const [routesLoading, setRoutesLoading] = reactExports.useState(false);
|
|
29430
|
+
async function loadRoutes() {
|
|
29431
|
+
setRoutesLoading(true);
|
|
29432
|
+
try {
|
|
29433
|
+
setRoutes(await fetchCaddyRoutes());
|
|
29434
|
+
} catch (err) {
|
|
29435
|
+
notifications.show({ color: "red", message: String(err) });
|
|
29436
|
+
setRoutes([]);
|
|
29437
|
+
} finally {
|
|
29438
|
+
setRoutesLoading(false);
|
|
29439
|
+
}
|
|
29440
|
+
}
|
|
29441
|
+
function openRoutes() {
|
|
29442
|
+
setRoutesOpen(true);
|
|
29443
|
+
void loadRoutes();
|
|
29444
|
+
}
|
|
29445
|
+
function renderRoutesBody() {
|
|
29446
|
+
if (routesLoading && routes === null) {
|
|
29447
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { justify: "center", gap: "xs", p: "lg", children: [
|
|
29448
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Loader, { size: "sm" }),
|
|
29449
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "불러오는 중..." })
|
|
29450
|
+
] });
|
|
29451
|
+
}
|
|
29452
|
+
const sorted = [...routes ?? []].sort((a, b) => {
|
|
29453
|
+
if (!!a.slug !== !!b.slug) return a.slug ? -1 : 1;
|
|
29454
|
+
const s = (a.slug ?? "").localeCompare(b.slug ?? "");
|
|
29455
|
+
return s !== 0 ? s : (a.appName ?? "").localeCompare(b.appName ?? "");
|
|
29456
|
+
});
|
|
29457
|
+
if (sorted.length === 0) {
|
|
29458
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", p: "md", children: "등록된 라우트가 없습니다." });
|
|
29459
|
+
}
|
|
29460
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Stack, { gap: "sm", children: [
|
|
29461
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { justify: "space-between", children: [
|
|
29462
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
29463
|
+
"총 ",
|
|
29464
|
+
sorted.length,
|
|
29465
|
+
"개"
|
|
29466
|
+
] }),
|
|
29467
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "compact-xs", variant: "subtle", loading: routesLoading, onClick: () => void loadRoutes(), children: "새로고침" })
|
|
29468
|
+
] }),
|
|
29469
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Table, { striped: true, highlightOnHover: true, horizontalSpacing: "md", verticalSpacing: "xs", children: [
|
|
29470
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Thead, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tr, { children: [
|
|
29471
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Th, { children: "워크스페이스" }),
|
|
29472
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Th, { children: "앱" }),
|
|
29473
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Th, { children: "호스트" }),
|
|
29474
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Th, { children: "업스트림" })
|
|
29475
|
+
] }) }),
|
|
29476
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Tbody, { children: sorted.map((r2, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tr, { children: [
|
|
29477
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: r2.slug ? /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "light", color: "grape", children: r2.slug }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "xs", c: "dimmed", children: "(기타)" }) }),
|
|
29478
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", children: r2.appName ?? (r2.handlers.join(", ") || "-") }) }),
|
|
29479
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: r2.hosts.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "-" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Stack, { gap: 2, children: r2.hosts.map((h) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29480
|
+
Anchor,
|
|
29481
|
+
{
|
|
29482
|
+
size: "sm",
|
|
29483
|
+
onClick: (e) => {
|
|
29484
|
+
e.preventDefault();
|
|
29485
|
+
void openExternal(`https://${h}`);
|
|
29486
|
+
},
|
|
29487
|
+
children: h
|
|
29488
|
+
},
|
|
29489
|
+
h
|
|
29490
|
+
)) }) }),
|
|
29491
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: r2.upstreams.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "-" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Stack, { gap: 2, children: r2.upstreams.map((u) => /* @__PURE__ */ jsxRuntimeExports.jsx(Code, { children: u }, u)) }) })
|
|
29492
|
+
] }, r2.id ?? `route-${i}`)) })
|
|
29493
|
+
] })
|
|
29494
|
+
] });
|
|
29495
|
+
}
|
|
29358
29496
|
async function act(action) {
|
|
29359
29497
|
try {
|
|
29360
29498
|
await caddyAction(action);
|
|
@@ -29419,73 +29557,100 @@ function CaddyView({ caddy, onLogs, onChanged, openLogKey }) {
|
|
|
29419
29557
|
] }) })
|
|
29420
29558
|
] });
|
|
29421
29559
|
}
|
|
29422
|
-
return /* @__PURE__ */ jsxRuntimeExports.
|
|
29423
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(Table.
|
|
29424
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
29425
|
-
|
|
29426
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29427
|
-
|
|
29428
|
-
"
|
|
29429
|
-
|
|
29430
|
-
|
|
29431
|
-
|
|
29432
|
-
"
|
|
29433
|
-
|
|
29434
|
-
|
|
29435
|
-
|
|
29436
|
-
|
|
29437
|
-
|
|
29438
|
-
|
|
29439
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
29440
|
-
|
|
29441
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29442
|
-
|
|
29443
|
-
|
|
29444
|
-
|
|
29445
|
-
|
|
29446
|
-
e
|
|
29447
|
-
|
|
29448
|
-
|
|
29449
|
-
|
|
29450
|
-
|
|
29451
|
-
|
|
29452
|
-
|
|
29453
|
-
|
|
29454
|
-
|
|
29455
|
-
|
|
29456
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
29457
|
-
|
|
29458
|
-
|
|
29459
|
-
|
|
29460
|
-
|
|
29461
|
-
|
|
29462
|
-
|
|
29463
|
-
|
|
29464
|
-
|
|
29465
|
-
|
|
29466
|
-
|
|
29467
|
-
|
|
29468
|
-
|
|
29469
|
-
|
|
29470
|
-
|
|
29471
|
-
|
|
29472
|
-
|
|
29473
|
-
|
|
29474
|
-
|
|
29475
|
-
|
|
29476
|
-
|
|
29477
|
-
|
|
29478
|
-
|
|
29479
|
-
|
|
29480
|
-
|
|
29481
|
-
|
|
29482
|
-
|
|
29483
|
-
|
|
29484
|
-
|
|
29485
|
-
|
|
29486
|
-
|
|
29487
|
-
|
|
29488
|
-
|
|
29560
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Stack, { gap: "xl", children: [
|
|
29561
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SectionCard, { title: "Caddy (시스템 공유 HTTPS 리버스 프록시)", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Table, { verticalSpacing: "sm", horizontalSpacing: "md", layout: "fixed", className: classes$6.table, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tbody, { children: [
|
|
29562
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tr, { children: [
|
|
29563
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { w: 200, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "상태" }) }),
|
|
29564
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { gap: 8, children: [
|
|
29565
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusBadge, { status, label }),
|
|
29566
|
+
((_a = caddy.proc) == null ? void 0 : _a.pid) ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
29567
|
+
"PID ",
|
|
29568
|
+
caddy.proc.pid
|
|
29569
|
+
] }) : null,
|
|
29570
|
+
((_b = caddy.proc) == null ? void 0 : _b.restarts) ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { size: "xs", variant: "light", color: "gray", children: [
|
|
29571
|
+
"재시작 ",
|
|
29572
|
+
caddy.proc.restarts,
|
|
29573
|
+
"회"
|
|
29574
|
+
] }) : null
|
|
29575
|
+
] }) })
|
|
29576
|
+
] }),
|
|
29577
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tr, { children: [
|
|
29578
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "Admin API" }) }),
|
|
29579
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { gap: 8, children: [
|
|
29580
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29581
|
+
Anchor,
|
|
29582
|
+
{
|
|
29583
|
+
size: "sm",
|
|
29584
|
+
onClick: (e) => {
|
|
29585
|
+
e.preventDefault();
|
|
29586
|
+
void openExternal(`${caddy.adminUrl}/config/`);
|
|
29587
|
+
},
|
|
29588
|
+
children: caddy.adminUrl
|
|
29589
|
+
}
|
|
29590
|
+
),
|
|
29591
|
+
caddy.reachable ? /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { size: "xs", color: "teal", variant: "light", children: "응답" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { size: "xs", color: "gray", variant: "light", children: "미응답" })
|
|
29592
|
+
] }) })
|
|
29593
|
+
] }),
|
|
29594
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tr, { children: [
|
|
29595
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "등록 라우트" }) }),
|
|
29596
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: caddy.routeCount === null ? /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "-" }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { gap: 6, wrap: "nowrap", children: [
|
|
29597
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Code, { children: caddy.routeCount }),
|
|
29598
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: "등록된 라우트 보기", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29599
|
+
ActionIcon,
|
|
29600
|
+
{
|
|
29601
|
+
size: "sm",
|
|
29602
|
+
variant: "subtle",
|
|
29603
|
+
color: "gray",
|
|
29604
|
+
disabled: !caddy.routeCount,
|
|
29605
|
+
onClick: openRoutes,
|
|
29606
|
+
"aria-label": "등록된 라우트 보기",
|
|
29607
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconSearch, { size: 14 })
|
|
29608
|
+
}
|
|
29609
|
+
) })
|
|
29610
|
+
] }) })
|
|
29611
|
+
] }),
|
|
29612
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tr, { children: [
|
|
29613
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "관리" }) }),
|
|
29614
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { gap: 6, children: [
|
|
29615
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29616
|
+
Button,
|
|
29617
|
+
{
|
|
29618
|
+
size: "compact-xs",
|
|
29619
|
+
variant: "default",
|
|
29620
|
+
onClick: () => onLogs({
|
|
29621
|
+
streamKey: caddyStreamKey(),
|
|
29622
|
+
title: "caddy (시스템)",
|
|
29623
|
+
openStream: openCaddyLogStream,
|
|
29624
|
+
actions: acts,
|
|
29625
|
+
onClear: () => clearCaddyLogs(),
|
|
29626
|
+
timestamped: false
|
|
29627
|
+
}),
|
|
29628
|
+
children: "로그"
|
|
29629
|
+
}
|
|
29630
|
+
),
|
|
29631
|
+
acts.map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "compact-xs", variant: "light", color: a.color, onClick: a.run, children: a.label }, a.label))
|
|
29632
|
+
] }) })
|
|
29633
|
+
] }),
|
|
29634
|
+
pathRow("데이터 디렉터리", caddy.dataDir),
|
|
29635
|
+
pathRow("부트스트랩 config", caddy.bootstrapFile, true),
|
|
29636
|
+
pathRow("로그 파일", caddy.logFile, true),
|
|
29637
|
+
caddy.error ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Table.Tr, { children: [
|
|
29638
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "dimmed", children: "에러" }) }),
|
|
29639
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Table.Td, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "sm", c: "red", children: caddy.error }) })
|
|
29640
|
+
] }) : null
|
|
29641
|
+
] }) }) }),
|
|
29642
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29643
|
+
Modal,
|
|
29644
|
+
{
|
|
29645
|
+
opened: routesOpen,
|
|
29646
|
+
onClose: () => setRoutesOpen(false),
|
|
29647
|
+
title: "등록된 Caddy 라우트",
|
|
29648
|
+
size: "min(1000px, 90vw)",
|
|
29649
|
+
centered: true,
|
|
29650
|
+
children: renderRoutesBody()
|
|
29651
|
+
}
|
|
29652
|
+
)
|
|
29653
|
+
] });
|
|
29489
29654
|
}
|
|
29490
29655
|
const bar = "_bar_8l5j4_5";
|
|
29491
29656
|
const search = "_search_8l5j4_15";
|
package/dist/ui/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Devis</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-0_fn9uMh.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="./assets/index-BDxL9RBN.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gbdx/devis",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Local development dashboard for pnpm monorepos — workspace scanning, process management, HTTPS proxy, Docker, and more.",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"author": "gibigspub@gmail.com",
|