@gbdx/devis 1.0.0 → 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.
|
@@ -28482,104 +28482,120 @@ const createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
|
28482
28482
|
* This source code is licensed under the MIT license.
|
|
28483
28483
|
* See the LICENSE file in the root directory of this source tree.
|
|
28484
28484
|
*/
|
|
28485
|
-
const __iconNode$
|
|
28486
|
-
const IconBolt = createReactComponent("outline", "bolt", "Bolt", __iconNode$
|
|
28485
|
+
const __iconNode$e = [["path", { "d": "M13 3l0 7l6 0l-8 11l0 -7l-6 0l8 -11", "key": "svg-0" }]];
|
|
28486
|
+
const IconBolt = createReactComponent("outline", "bolt", "Bolt", __iconNode$e);
|
|
28487
28487
|
/**
|
|
28488
28488
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28489
28489
|
*
|
|
28490
28490
|
* This source code is licensed under the MIT license.
|
|
28491
28491
|
* See the LICENSE file in the root directory of this source tree.
|
|
28492
28492
|
*/
|
|
28493
|
-
const __iconNode$
|
|
28494
|
-
const IconBrandVscode = createReactComponent("outline", "brand-vscode", "BrandVscode", __iconNode$
|
|
28493
|
+
const __iconNode$d = [["path", { "d": "M16 3v18l4 -2.5v-13l-4 -2.5", "key": "svg-0" }], ["path", { "d": "M9.165 13.903l-4.165 3.597l-2 -1l4.333 -4.5m1.735 -1.802l6.932 -7.198v5l-4.795 4.141", "key": "svg-1" }], ["path", { "d": "M16 16.5l-11 -10l-2 1l13 13.5", "key": "svg-2" }]];
|
|
28494
|
+
const IconBrandVscode = createReactComponent("outline", "brand-vscode", "BrandVscode", __iconNode$d);
|
|
28495
28495
|
/**
|
|
28496
28496
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28497
28497
|
*
|
|
28498
28498
|
* This source code is licensed under the MIT license.
|
|
28499
28499
|
* See the LICENSE file in the root directory of this source tree.
|
|
28500
28500
|
*/
|
|
28501
|
-
const __iconNode$
|
|
28502
|
-
const IconChevronDown = createReactComponent("outline", "chevron-down", "ChevronDown", __iconNode$
|
|
28501
|
+
const __iconNode$c = [["path", { "d": "M6 9l6 6l6 -6", "key": "svg-0" }]];
|
|
28502
|
+
const IconChevronDown = createReactComponent("outline", "chevron-down", "ChevronDown", __iconNode$c);
|
|
28503
28503
|
/**
|
|
28504
28504
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28505
28505
|
*
|
|
28506
28506
|
* This source code is licensed under the MIT license.
|
|
28507
28507
|
* See the LICENSE file in the root directory of this source tree.
|
|
28508
28508
|
*/
|
|
28509
|
-
const __iconNode$
|
|
28510
|
-
const
|
|
28509
|
+
const __iconNode$b = [["path", { "d": "M6 15l6 -6l6 6", "key": "svg-0" }]];
|
|
28510
|
+
const IconChevronUp = createReactComponent("outline", "chevron-up", "ChevronUp", __iconNode$b);
|
|
28511
28511
|
/**
|
|
28512
28512
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28513
28513
|
*
|
|
28514
28514
|
* This source code is licensed under the MIT license.
|
|
28515
28515
|
* See the LICENSE file in the root directory of this source tree.
|
|
28516
28516
|
*/
|
|
28517
|
-
const __iconNode$
|
|
28518
|
-
const
|
|
28517
|
+
const __iconNode$a = [["path", { "d": "M14 3v4a1 1 0 0 0 1 1h4", "key": "svg-0" }], ["path", { "d": "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2", "key": "svg-1" }], ["path", { "d": "M9 9l1 0", "key": "svg-2" }], ["path", { "d": "M9 13l6 0", "key": "svg-3" }], ["path", { "d": "M9 17l6 0", "key": "svg-4" }]];
|
|
28518
|
+
const IconFileText = createReactComponent("outline", "file-text", "FileText", __iconNode$a);
|
|
28519
28519
|
/**
|
|
28520
28520
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28521
28521
|
*
|
|
28522
28522
|
* This source code is licensed under the MIT license.
|
|
28523
28523
|
* See the LICENSE file in the root directory of this source tree.
|
|
28524
28524
|
*/
|
|
28525
|
-
const __iconNode$
|
|
28526
|
-
const
|
|
28525
|
+
const __iconNode$9 = [["path", { "d": "M5 19l2.757 -7.351a1 1 0 0 1 .936 -.649h12.307a1 1 0 0 1 .986 1.164l-.996 5.211a2 2 0 0 1 -1.964 1.625h-14.026a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2h4l3 3h7a2 2 0 0 1 2 2v2", "key": "svg-0" }]];
|
|
28526
|
+
const IconFolderOpen = createReactComponent("outline", "folder-open", "FolderOpen", __iconNode$9);
|
|
28527
28527
|
/**
|
|
28528
28528
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28529
28529
|
*
|
|
28530
28530
|
* This source code is licensed under the MIT license.
|
|
28531
28531
|
* See the LICENSE file in the root directory of this source tree.
|
|
28532
28532
|
*/
|
|
28533
|
-
const __iconNode$
|
|
28534
|
-
const
|
|
28533
|
+
const __iconNode$8 = [["path", { "d": "M12 19h-7a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2h4l3 3h7a2 2 0 0 1 2 2v3.5", "key": "svg-0" }], ["path", { "d": "M16 19h6", "key": "svg-1" }], ["path", { "d": "M19 16v6", "key": "svg-2" }]];
|
|
28534
|
+
const IconFolderPlus = createReactComponent("outline", "folder-plus", "FolderPlus", __iconNode$8);
|
|
28535
28535
|
/**
|
|
28536
28536
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28537
28537
|
*
|
|
28538
28538
|
* This source code is licensed under the MIT license.
|
|
28539
28539
|
* See the LICENSE file in the root directory of this source tree.
|
|
28540
28540
|
*/
|
|
28541
|
-
const __iconNode$
|
|
28542
|
-
const
|
|
28541
|
+
const __iconNode$7 = [["path", { "d": "M4 6l16 0", "key": "svg-0" }], ["path", { "d": "M4 12l16 0", "key": "svg-1" }], ["path", { "d": "M4 18l16 0", "key": "svg-2" }]];
|
|
28542
|
+
const IconMenu2 = createReactComponent("outline", "menu-2", "Menu2", __iconNode$7);
|
|
28543
28543
|
/**
|
|
28544
28544
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28545
28545
|
*
|
|
28546
28546
|
* This source code is licensed under the MIT license.
|
|
28547
28547
|
* See the LICENSE file in the root directory of this source tree.
|
|
28548
28548
|
*/
|
|
28549
|
-
const __iconNode$
|
|
28550
|
-
const
|
|
28549
|
+
const __iconNode$6 = [["path", { "d": "M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454l0 .008", "key": "svg-0" }]];
|
|
28550
|
+
const IconMoon = createReactComponent("outline", "moon", "Moon", __iconNode$6);
|
|
28551
28551
|
/**
|
|
28552
28552
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28553
28553
|
*
|
|
28554
28554
|
* This source code is licensed under the MIT license.
|
|
28555
28555
|
* See the LICENSE file in the root directory of this source tree.
|
|
28556
28556
|
*/
|
|
28557
|
-
const __iconNode$
|
|
28558
|
-
const
|
|
28557
|
+
const __iconNode$5 = [["path", { "d": "M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4", "key": "svg-0" }], ["path", { "d": "M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4", "key": "svg-1" }]];
|
|
28558
|
+
const IconRefresh = createReactComponent("outline", "refresh", "Refresh", __iconNode$5);
|
|
28559
28559
|
/**
|
|
28560
28560
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28561
28561
|
*
|
|
28562
28562
|
* This source code is licensed under the MIT license.
|
|
28563
28563
|
* See the LICENSE file in the root directory of this source tree.
|
|
28564
28564
|
*/
|
|
28565
|
-
const __iconNode$
|
|
28566
|
-
const
|
|
28565
|
+
const __iconNode$4 = [["path", { "d": "M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0", "key": "svg-0" }], ["path", { "d": "M21 21l-6 -6", "key": "svg-1" }]];
|
|
28566
|
+
const IconSearch = createReactComponent("outline", "search", "Search", __iconNode$4);
|
|
28567
28567
|
/**
|
|
28568
28568
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28569
28569
|
*
|
|
28570
28570
|
* This source code is licensed under the MIT license.
|
|
28571
28571
|
* See the LICENSE file in the root directory of this source tree.
|
|
28572
28572
|
*/
|
|
28573
|
-
const __iconNode$
|
|
28574
|
-
const
|
|
28573
|
+
const __iconNode$3 = [["path", { "d": "M8 12a4 4 0 1 0 8 0a4 4 0 1 0 -8 0", "key": "svg-0" }], ["path", { "d": "M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7", "key": "svg-1" }]];
|
|
28574
|
+
const IconSun = createReactComponent("outline", "sun", "Sun", __iconNode$3);
|
|
28575
28575
|
/**
|
|
28576
28576
|
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28577
28577
|
*
|
|
28578
28578
|
* This source code is licensed under the MIT license.
|
|
28579
28579
|
* See the LICENSE file in the root directory of this source tree.
|
|
28580
28580
|
*/
|
|
28581
|
-
const __iconNode = [["path", { "d": "
|
|
28582
|
-
const
|
|
28581
|
+
const __iconNode$2 = [["path", { "d": "M8 9l3 3l-3 3", "key": "svg-0" }], ["path", { "d": "M13 15l3 0", "key": "svg-1" }], ["path", { "d": "M3 6a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2l0 -12", "key": "svg-2" }]];
|
|
28582
|
+
const IconTerminal2 = createReactComponent("outline", "terminal-2", "Terminal2", __iconNode$2);
|
|
28583
|
+
/**
|
|
28584
|
+
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28585
|
+
*
|
|
28586
|
+
* This source code is licensed under the MIT license.
|
|
28587
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
28588
|
+
*/
|
|
28589
|
+
const __iconNode$1 = [["path", { "d": "M4 7l16 0", "key": "svg-0" }], ["path", { "d": "M10 11l0 6", "key": "svg-1" }], ["path", { "d": "M14 11l0 6", "key": "svg-2" }], ["path", { "d": "M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12", "key": "svg-3" }], ["path", { "d": "M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3", "key": "svg-4" }]];
|
|
28590
|
+
const IconTrash = createReactComponent("outline", "trash", "Trash", __iconNode$1);
|
|
28591
|
+
/**
|
|
28592
|
+
* @license @tabler/icons-react v3.44.0 - MIT
|
|
28593
|
+
*
|
|
28594
|
+
* This source code is licensed under the MIT license.
|
|
28595
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
28596
|
+
*/
|
|
28597
|
+
const __iconNode = [["path", { "d": "M18 6l-12 12", "key": "svg-0" }], ["path", { "d": "M6 6l12 12", "key": "svg-1" }]];
|
|
28598
|
+
const IconX = createReactComponent("outline", "x", "X", __iconNode);
|
|
28583
28599
|
const header$2 = "_header_1cfdg_1";
|
|
28584
28600
|
const headerInner = "_headerInner_1cfdg_6";
|
|
28585
28601
|
const brand = "_brand_1cfdg_12";
|
|
@@ -29099,6 +29115,75 @@ async function fetchCaddyRouteCount() {
|
|
|
29099
29115
|
return null;
|
|
29100
29116
|
}
|
|
29101
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
|
+
}
|
|
29102
29187
|
function caddyPaths() {
|
|
29103
29188
|
const home = getGlobalContext().homeDir;
|
|
29104
29189
|
return {
|
|
@@ -29339,6 +29424,75 @@ function statusLabel(info) {
|
|
|
29339
29424
|
}
|
|
29340
29425
|
function CaddyView({ caddy, onLogs, onChanged, openLogKey }) {
|
|
29341
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
|
+
}
|
|
29342
29496
|
async function act(action) {
|
|
29343
29497
|
try {
|
|
29344
29498
|
await caddyAction(action);
|
|
@@ -29403,73 +29557,100 @@ function CaddyView({ caddy, onLogs, onChanged, openLogKey }) {
|
|
|
29403
29557
|
] }) })
|
|
29404
29558
|
] });
|
|
29405
29559
|
}
|
|
29406
|
-
return /* @__PURE__ */ jsxRuntimeExports.
|
|
29407
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(Table.
|
|
29408
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
29409
|
-
|
|
29410
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29411
|
-
|
|
29412
|
-
"
|
|
29413
|
-
|
|
29414
|
-
|
|
29415
|
-
|
|
29416
|
-
"
|
|
29417
|
-
|
|
29418
|
-
|
|
29419
|
-
|
|
29420
|
-
|
|
29421
|
-
|
|
29422
|
-
|
|
29423
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
29424
|
-
|
|
29425
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29426
|
-
|
|
29427
|
-
|
|
29428
|
-
|
|
29429
|
-
|
|
29430
|
-
e
|
|
29431
|
-
|
|
29432
|
-
|
|
29433
|
-
|
|
29434
|
-
|
|
29435
|
-
|
|
29436
|
-
|
|
29437
|
-
|
|
29438
|
-
|
|
29439
|
-
|
|
29440
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
29441
|
-
|
|
29442
|
-
|
|
29443
|
-
|
|
29444
|
-
|
|
29445
|
-
|
|
29446
|
-
|
|
29447
|
-
|
|
29448
|
-
|
|
29449
|
-
|
|
29450
|
-
|
|
29451
|
-
|
|
29452
|
-
|
|
29453
|
-
|
|
29454
|
-
|
|
29455
|
-
|
|
29456
|
-
|
|
29457
|
-
|
|
29458
|
-
|
|
29459
|
-
|
|
29460
|
-
|
|
29461
|
-
|
|
29462
|
-
|
|
29463
|
-
|
|
29464
|
-
|
|
29465
|
-
|
|
29466
|
-
|
|
29467
|
-
|
|
29468
|
-
|
|
29469
|
-
|
|
29470
|
-
|
|
29471
|
-
|
|
29472
|
-
|
|
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
|
+
] });
|
|
29473
29654
|
}
|
|
29474
29655
|
const bar = "_bar_8l5j4_5";
|
|
29475
29656
|
const search = "_search_8l5j4_15";
|
|
@@ -31506,6 +31687,60 @@ function segStyle(seg) {
|
|
|
31506
31687
|
textDecoration: d.includes("underline") ? "underline" : void 0
|
|
31507
31688
|
};
|
|
31508
31689
|
}
|
|
31690
|
+
const MATCH_STYLE = { background: "var(--mantine-color-yellow-4)", color: "#000" };
|
|
31691
|
+
const ACTIVE_MATCH_STYLE = { background: "var(--mantine-color-orange-5)", color: "#000" };
|
|
31692
|
+
function highlightSegments(entry, query, activeStart) {
|
|
31693
|
+
const lower = entry.text.toLowerCase();
|
|
31694
|
+
const ranges = [];
|
|
31695
|
+
let from = 0;
|
|
31696
|
+
while (query) {
|
|
31697
|
+
const idx = lower.indexOf(query, from);
|
|
31698
|
+
if (idx === -1) break;
|
|
31699
|
+
ranges.push([idx, idx + query.length]);
|
|
31700
|
+
from = idx + query.length;
|
|
31701
|
+
}
|
|
31702
|
+
if (ranges.length === 0) {
|
|
31703
|
+
return entry.segments.map((seg, i) => (
|
|
31704
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: 파싱된 로그 줄은 불변
|
|
31705
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: segStyle(seg), children: seg.content }, i)
|
|
31706
|
+
));
|
|
31707
|
+
}
|
|
31708
|
+
const nodes = [];
|
|
31709
|
+
let offset2 = 0;
|
|
31710
|
+
let key = 0;
|
|
31711
|
+
for (const seg of entry.segments) {
|
|
31712
|
+
const base = segStyle(seg);
|
|
31713
|
+
const text = seg.content;
|
|
31714
|
+
const segStart = offset2;
|
|
31715
|
+
const segEnd = offset2 + text.length;
|
|
31716
|
+
let pos = segStart;
|
|
31717
|
+
while (pos < segEnd) {
|
|
31718
|
+
const range = ranges.find(([, e]) => e > pos);
|
|
31719
|
+
if (!range || range[0] >= segEnd) {
|
|
31720
|
+
nodes.push(
|
|
31721
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: base, children: text.slice(pos - segStart) }, `s${key++}`)
|
|
31722
|
+
);
|
|
31723
|
+
break;
|
|
31724
|
+
}
|
|
31725
|
+
const [ms, me] = range;
|
|
31726
|
+
if (pos < ms) {
|
|
31727
|
+
nodes.push(
|
|
31728
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: base, children: text.slice(pos - segStart, ms - segStart) }, `s${key++}`)
|
|
31729
|
+
);
|
|
31730
|
+
pos = ms;
|
|
31731
|
+
} else {
|
|
31732
|
+
const end = Math.min(me, segEnd);
|
|
31733
|
+
const mark = ms === activeStart ? ACTIVE_MATCH_STYLE : MATCH_STYLE;
|
|
31734
|
+
nodes.push(
|
|
31735
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { ...base, ...mark }, children: text.slice(pos - segStart, end - segStart) }, `s${key++}`)
|
|
31736
|
+
);
|
|
31737
|
+
pos = end;
|
|
31738
|
+
}
|
|
31739
|
+
}
|
|
31740
|
+
offset2 = segEnd;
|
|
31741
|
+
}
|
|
31742
|
+
return nodes;
|
|
31743
|
+
}
|
|
31509
31744
|
const ANSER_OPTS = { json: true, remove_empty: true, use_classes: false };
|
|
31510
31745
|
const TS_PREFIX = /^\d{4}-\d{2}-\d{2}T\d{2}:/;
|
|
31511
31746
|
function parseLine(raw, timestamped) {
|
|
@@ -31514,13 +31749,17 @@ function parseLine(raw, timestamped) {
|
|
|
31514
31749
|
if (sp > 0) {
|
|
31515
31750
|
const ts = raw.slice(0, sp);
|
|
31516
31751
|
if (TS_PREFIX.test(ts)) {
|
|
31517
|
-
return
|
|
31752
|
+
return makeEntry(raw.slice(sp + 1), ts);
|
|
31518
31753
|
}
|
|
31519
31754
|
}
|
|
31520
31755
|
}
|
|
31521
|
-
return
|
|
31756
|
+
return makeEntry(raw);
|
|
31522
31757
|
}
|
|
31523
|
-
function
|
|
31758
|
+
function makeEntry(content, timestamp) {
|
|
31759
|
+
const segments = Anser.ansiToJson(content, ANSER_OPTS);
|
|
31760
|
+
return { timestamp, segments, text: segments.map((s) => s.content).join("") };
|
|
31761
|
+
}
|
|
31762
|
+
const LogStream = reactExports.forwardRef(function LogStream2({ openStream, clearSignal, timestamped, loadHistory, query = "", onMatchState }, ref) {
|
|
31524
31763
|
const [lines, setLines] = reactExports.useState([]);
|
|
31525
31764
|
const [reachedStart, setReachedStart] = reactExports.useState(false);
|
|
31526
31765
|
const [loadingHistory, setLoadingHistory] = reactExports.useState(false);
|
|
@@ -31572,12 +31811,59 @@ function LogStream({ openStream, clearSignal, timestamped, loadHistory }) {
|
|
|
31572
31811
|
estimateSize: () => LINE_HEIGHT,
|
|
31573
31812
|
overscan: 24
|
|
31574
31813
|
});
|
|
31814
|
+
const q = query.trim().toLowerCase();
|
|
31815
|
+
const matches = reactExports.useMemo(() => {
|
|
31816
|
+
if (!q) return [];
|
|
31817
|
+
const out = [];
|
|
31818
|
+
for (let i = 0; i < lines.length; i++) {
|
|
31819
|
+
const lower = lines[i].text.toLowerCase();
|
|
31820
|
+
let pos = lower.indexOf(q);
|
|
31821
|
+
while (pos !== -1) {
|
|
31822
|
+
out.push({ line: i, start: pos });
|
|
31823
|
+
pos = lower.indexOf(q, pos + q.length);
|
|
31824
|
+
}
|
|
31825
|
+
}
|
|
31826
|
+
return out;
|
|
31827
|
+
}, [lines, q]);
|
|
31828
|
+
const matchLineSet = reactExports.useMemo(() => new Set(matches.map((m) => m.line)), [matches]);
|
|
31829
|
+
const matchesRef = reactExports.useRef(matches);
|
|
31830
|
+
matchesRef.current = matches;
|
|
31831
|
+
const [cursor, setCursor] = reactExports.useState(0);
|
|
31832
|
+
const total = matches.length;
|
|
31833
|
+
const safeCursor = total === 0 ? 0 : Math.min(cursor, total - 1);
|
|
31834
|
+
const activeMatch = total === 0 ? null : matches[safeCursor];
|
|
31835
|
+
const cursorRef = reactExports.useRef(safeCursor);
|
|
31836
|
+
cursorRef.current = safeCursor;
|
|
31837
|
+
reactExports.useEffect(() => {
|
|
31838
|
+
onMatchState == null ? void 0 : onMatchState({ current: total === 0 ? 0 : safeCursor + 1, total });
|
|
31839
|
+
}, [total, safeCursor, onMatchState]);
|
|
31840
|
+
reactExports.useEffect(() => {
|
|
31841
|
+
cursorRef.current = 0;
|
|
31842
|
+
setCursor(0);
|
|
31843
|
+
if (q && matchesRef.current.length > 0) {
|
|
31844
|
+
stick.current = false;
|
|
31845
|
+
virtualizer.scrollToIndex(matchesRef.current[0].line, { align: "center" });
|
|
31846
|
+
}
|
|
31847
|
+
}, [q]);
|
|
31848
|
+
const navigate = reactExports.useCallback(
|
|
31849
|
+
(dir) => {
|
|
31850
|
+
const items = matchesRef.current;
|
|
31851
|
+
if (items.length === 0) return;
|
|
31852
|
+
const nextC = (cursorRef.current + dir + items.length) % items.length;
|
|
31853
|
+
cursorRef.current = nextC;
|
|
31854
|
+
stick.current = false;
|
|
31855
|
+
setCursor(nextC);
|
|
31856
|
+
virtualizer.scrollToIndex(items[nextC].line, { align: "center" });
|
|
31857
|
+
},
|
|
31858
|
+
[virtualizer]
|
|
31859
|
+
);
|
|
31860
|
+
reactExports.useImperativeHandle(ref, () => ({ next: () => navigate(1), prev: () => navigate(-1) }), [navigate]);
|
|
31575
31861
|
reactExports.useEffect(() => {
|
|
31576
31862
|
if (restoreToIndex.current !== null) return;
|
|
31577
|
-
if (stick.current && lines.length > 0) {
|
|
31863
|
+
if (!q && stick.current && lines.length > 0) {
|
|
31578
31864
|
virtualizer.scrollToIndex(lines.length - 1, { align: "end" });
|
|
31579
31865
|
}
|
|
31580
|
-
}, [lines.length, virtualizer]);
|
|
31866
|
+
}, [lines.length, virtualizer, q]);
|
|
31581
31867
|
reactExports.useEffect(() => {
|
|
31582
31868
|
if (restoreToIndex.current === null) return;
|
|
31583
31869
|
const idx = restoreToIndex.current;
|
|
@@ -31657,35 +31943,69 @@ function LogStream({ openStream, clearSignal, timestamped, loadHistory }) {
|
|
|
31657
31943
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "↑ 위로 스크롤하면 과거 로그를 불러옵니다" })
|
|
31658
31944
|
}
|
|
31659
31945
|
) : null,
|
|
31660
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { height: virtualizer.getTotalSize(), position: "relative" }, children: virtualizer.getVirtualItems().map((vi) =>
|
|
31661
|
-
|
|
31662
|
-
|
|
31663
|
-
|
|
31664
|
-
|
|
31665
|
-
|
|
31666
|
-
"
|
|
31667
|
-
|
|
31668
|
-
|
|
31669
|
-
|
|
31670
|
-
|
|
31671
|
-
|
|
31672
|
-
|
|
31673
|
-
|
|
31674
|
-
|
|
31675
|
-
|
|
31676
|
-
|
|
31946
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { height: virtualizer.getTotalSize(), position: "relative" }, children: virtualizer.getVirtualItems().map((vi) => {
|
|
31947
|
+
const activeStart = activeMatch && activeMatch.line === vi.index ? activeMatch.start : -1;
|
|
31948
|
+
return (
|
|
31949
|
+
// data-index + measureElement ref — 줄바꿈된 긴 로그의 실제 높이를 측정해
|
|
31950
|
+
// 가상 스크롤 위치를 맞춘다 (고정 높이로 두면 긴 줄이 겹쳐 보인다).
|
|
31951
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31952
|
+
"div",
|
|
31953
|
+
{
|
|
31954
|
+
"data-index": vi.index,
|
|
31955
|
+
ref: virtualizer.measureElement,
|
|
31956
|
+
style: {
|
|
31957
|
+
position: "absolute",
|
|
31958
|
+
top: 0,
|
|
31959
|
+
left: 0,
|
|
31960
|
+
width: "100%",
|
|
31961
|
+
transform: `translateY(${vi.start}px)`,
|
|
31962
|
+
whiteSpace: "pre-wrap",
|
|
31963
|
+
wordBreak: "break-all",
|
|
31964
|
+
padding: "0 12px",
|
|
31965
|
+
background: activeStart !== -1 ? "var(--mantine-color-yellow-light)" : void 0
|
|
31966
|
+
},
|
|
31967
|
+
children: q && matchLineSet.has(vi.index) ? highlightSegments(lines[vi.index], q, activeStart) : lines[vi.index].segments.map((seg, i) => (
|
|
31968
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: 파싱된 로그 줄은 불변이라 세그먼트 순서가 바뀌지 않는다
|
|
31969
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: segStyle(seg), children: seg.content }, i)
|
|
31970
|
+
))
|
|
31677
31971
|
},
|
|
31678
|
-
|
|
31679
|
-
|
|
31680
|
-
|
|
31681
|
-
|
|
31682
|
-
},
|
|
31683
|
-
vi.key
|
|
31684
|
-
)
|
|
31685
|
-
)) })
|
|
31972
|
+
vi.key
|
|
31973
|
+
)
|
|
31974
|
+
);
|
|
31975
|
+
}) })
|
|
31686
31976
|
]
|
|
31687
31977
|
}
|
|
31688
31978
|
);
|
|
31979
|
+
});
|
|
31980
|
+
function LogSearchControls({ query, onQueryChange, match, onPrev, onNext }) {
|
|
31981
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
31982
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31983
|
+
TextInput,
|
|
31984
|
+
{
|
|
31985
|
+
size: "xs",
|
|
31986
|
+
w: 180,
|
|
31987
|
+
placeholder: "로그 찾기",
|
|
31988
|
+
leftSection: /* @__PURE__ */ jsxRuntimeExports.jsx(IconSearch, { size: 14 }),
|
|
31989
|
+
value: query,
|
|
31990
|
+
onChange: (e) => onQueryChange(e.currentTarget.value),
|
|
31991
|
+
onKeyDown: (e) => {
|
|
31992
|
+
if (e.key === "Enter") {
|
|
31993
|
+
e.preventDefault();
|
|
31994
|
+
if (e.shiftKey) onPrev();
|
|
31995
|
+
else onNext();
|
|
31996
|
+
} else if (e.key === "Escape") {
|
|
31997
|
+
onQueryChange("");
|
|
31998
|
+
}
|
|
31999
|
+
},
|
|
32000
|
+
rightSection: query ? /* @__PURE__ */ jsxRuntimeExports.jsx(ActionIcon, { size: "sm", variant: "subtle", color: "gray", onClick: () => onQueryChange(""), "aria-label": "검색어 지우기", children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconX, { size: 14 }) }) : null
|
|
32001
|
+
}
|
|
32002
|
+
),
|
|
32003
|
+
query ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
32004
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Text, { size: "xs", c: "dimmed", style: { fontVariantNumeric: "tabular-nums", minWidth: 36, textAlign: "right" }, children: match.total ? `${match.current}/${match.total}` : "0/0" }),
|
|
32005
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ActionIcon, { size: "sm", variant: "default", disabled: !match.total, onClick: onPrev, "aria-label": "이전 매치", children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconChevronUp, { size: 14 }) }),
|
|
32006
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ActionIcon, { size: "sm", variant: "default", disabled: !match.total, onClick: onNext, "aria-label": "다음 매치", children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconChevronDown, { size: 14 }) })
|
|
32007
|
+
] }) : null
|
|
32008
|
+
] });
|
|
31689
32009
|
}
|
|
31690
32010
|
const ROOT_FONT_PX = 16;
|
|
31691
32011
|
const MIN_HEIGHT_PX = 15 * ROOT_FONT_PX;
|
|
@@ -31706,6 +32026,9 @@ function writeStoredHeight(px2) {
|
|
|
31706
32026
|
function LogDrawer({ target, onClose }) {
|
|
31707
32027
|
var _a;
|
|
31708
32028
|
const [clearSignal, setClearSignal] = reactExports.useState(0);
|
|
32029
|
+
const [query, setQuery] = reactExports.useState("");
|
|
32030
|
+
const [match, setMatch] = reactExports.useState({ current: 0, total: 0 });
|
|
32031
|
+
const streamRef = reactExports.useRef(null);
|
|
31709
32032
|
const [height, setHeight] = reactExports.useState(() => {
|
|
31710
32033
|
if (typeof window === "undefined") return 480;
|
|
31711
32034
|
const stored = readStoredHeight();
|
|
@@ -31723,6 +32046,9 @@ function LogDrawer({ target, onClose }) {
|
|
|
31723
32046
|
if (resizing) return;
|
|
31724
32047
|
writeStoredHeight(height);
|
|
31725
32048
|
}, [resizing, height]);
|
|
32049
|
+
reactExports.useEffect(() => {
|
|
32050
|
+
setQuery("");
|
|
32051
|
+
}, [target == null ? void 0 : target.streamKey]);
|
|
31726
32052
|
async function handleClear() {
|
|
31727
32053
|
var _a2;
|
|
31728
32054
|
setClearSignal((n) => n + 1);
|
|
@@ -31778,6 +32104,22 @@ function LogDrawer({ target, onClose }) {
|
|
|
31778
32104
|
(_a = target == null ? void 0 : target.actions) == null ? void 0 : _a.map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "compact-xs", variant: "light", color: a.color, onClick: a.run, children: a.label }, a.label))
|
|
31779
32105
|
] }) }),
|
|
31780
32106
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Group, { gap: "xs", children: [
|
|
32107
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32108
|
+
LogSearchControls,
|
|
32109
|
+
{
|
|
32110
|
+
query,
|
|
32111
|
+
onQueryChange: setQuery,
|
|
32112
|
+
match,
|
|
32113
|
+
onPrev: () => {
|
|
32114
|
+
var _a2;
|
|
32115
|
+
return (_a2 = streamRef.current) == null ? void 0 : _a2.prev();
|
|
32116
|
+
},
|
|
32117
|
+
onNext: () => {
|
|
32118
|
+
var _a2;
|
|
32119
|
+
return (_a2 = streamRef.current) == null ? void 0 : _a2.next();
|
|
32120
|
+
}
|
|
32121
|
+
}
|
|
32122
|
+
),
|
|
31781
32123
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "compact-xs", variant: "default", onClick: () => void handleClear(), children: "Clear" }),
|
|
31782
32124
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Drawer.CloseButton, {})
|
|
31783
32125
|
] })
|
|
@@ -31785,10 +32127,13 @@ function LogDrawer({ target, onClose }) {
|
|
|
31785
32127
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Drawer.Body, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: classes$2.streamContainer, style: { height: `${height - 80}px` }, children: target !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31786
32128
|
LogStream,
|
|
31787
32129
|
{
|
|
32130
|
+
ref: streamRef,
|
|
31788
32131
|
openStream: target.openStream,
|
|
31789
32132
|
clearSignal,
|
|
31790
32133
|
timestamped: target.timestamped,
|
|
31791
|
-
loadHistory: target.loadHistory
|
|
32134
|
+
loadHistory: target.loadHistory,
|
|
32135
|
+
query,
|
|
32136
|
+
onMatchState: setMatch
|
|
31792
32137
|
},
|
|
31793
32138
|
target.streamKey
|
|
31794
32139
|
) }) })
|
|
@@ -32086,17 +32431,27 @@ function ProjectDetail({ opened, entry, workspaceRoot, initialSelection, procAct
|
|
|
32086
32431
|
var _a, _b;
|
|
32087
32432
|
const [selection, setSelection] = reactExports.useState(initialSelection ?? "log");
|
|
32088
32433
|
const [, force] = reactExports.useReducer((x) => x + 1, 0);
|
|
32434
|
+
const [query, setQuery] = reactExports.useState("");
|
|
32435
|
+
const [match, setMatch] = reactExports.useState({ current: 0, total: 0 });
|
|
32436
|
+
const streamRef = reactExports.useRef(null);
|
|
32089
32437
|
reactExports.useEffect(() => {
|
|
32090
|
-
if (opened)
|
|
32438
|
+
if (opened) {
|
|
32439
|
+
setSelection(initialSelection ?? "log");
|
|
32440
|
+
setQuery("");
|
|
32441
|
+
}
|
|
32091
32442
|
}, [opened, initialSelection]);
|
|
32092
32443
|
reactExports.useEffect(() => {
|
|
32093
32444
|
return subscribe(() => force());
|
|
32094
32445
|
}, []);
|
|
32446
|
+
reactExports.useEffect(() => {
|
|
32447
|
+
setQuery("");
|
|
32448
|
+
}, [selection]);
|
|
32095
32449
|
if (!entry) return null;
|
|
32096
32450
|
const procName = (_a = entry.proc) == null ? void 0 : _a.name;
|
|
32097
32451
|
const procDisplayName = (_b = entry.proc) == null ? void 0 : _b.displayName;
|
|
32098
32452
|
const projectKey = procDisplayName ?? entry.name.split("/").pop() ?? entry.name;
|
|
32099
32453
|
const processes = listProcesses(projectKey);
|
|
32454
|
+
const streamShown = selection === "log" ? Boolean(procName) : Boolean(getProcess(selection));
|
|
32100
32455
|
function handleSelectScript(scriptName) {
|
|
32101
32456
|
if (!(entry == null ? void 0 : entry.dir)) return;
|
|
32102
32457
|
const id = startScript(
|
|
@@ -32125,9 +32480,12 @@ function ProjectDetail({ opened, entry, workspaceRoot, initialSelection, procAct
|
|
|
32125
32480
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32126
32481
|
LogStream,
|
|
32127
32482
|
{
|
|
32483
|
+
ref: streamRef,
|
|
32128
32484
|
openStream: () => openPm2LogStream(procName),
|
|
32129
32485
|
clearSignal: 0,
|
|
32130
|
-
timestamped: false
|
|
32486
|
+
timestamped: false,
|
|
32487
|
+
query,
|
|
32488
|
+
onMatchState: setMatch
|
|
32131
32489
|
},
|
|
32132
32490
|
"pm2-log"
|
|
32133
32491
|
);
|
|
@@ -32139,9 +32497,12 @@ function ProjectDetail({ opened, entry, workspaceRoot, initialSelection, procAct
|
|
|
32139
32497
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32140
32498
|
LogStream,
|
|
32141
32499
|
{
|
|
32500
|
+
ref: streamRef,
|
|
32142
32501
|
openStream: () => openScriptStream(proc.id),
|
|
32143
32502
|
clearSignal: 0,
|
|
32144
|
-
timestamped: false
|
|
32503
|
+
timestamped: false,
|
|
32504
|
+
query,
|
|
32505
|
+
onMatchState: setMatch
|
|
32145
32506
|
},
|
|
32146
32507
|
`script-${proc.id}`
|
|
32147
32508
|
);
|
|
@@ -32221,7 +32582,35 @@ function ProjectDetail({ opened, entry, workspaceRoot, initialSelection, procAct
|
|
|
32221
32582
|
]
|
|
32222
32583
|
}
|
|
32223
32584
|
),
|
|
32224
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
32585
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { style: { flex: "1 1 auto", minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
|
|
32586
|
+
streamShown ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32587
|
+
Group,
|
|
32588
|
+
{
|
|
32589
|
+
justify: "flex-end",
|
|
32590
|
+
gap: "xs",
|
|
32591
|
+
px: "xs",
|
|
32592
|
+
py: 6,
|
|
32593
|
+
style: { flex: "0 0 auto", borderBottom: "1px solid var(--mantine-color-default-border)" },
|
|
32594
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32595
|
+
LogSearchControls,
|
|
32596
|
+
{
|
|
32597
|
+
query,
|
|
32598
|
+
onQueryChange: setQuery,
|
|
32599
|
+
match,
|
|
32600
|
+
onPrev: () => {
|
|
32601
|
+
var _a2;
|
|
32602
|
+
return (_a2 = streamRef.current) == null ? void 0 : _a2.prev();
|
|
32603
|
+
},
|
|
32604
|
+
onNext: () => {
|
|
32605
|
+
var _a2;
|
|
32606
|
+
return (_a2 = streamRef.current) == null ? void 0 : _a2.next();
|
|
32607
|
+
}
|
|
32608
|
+
}
|
|
32609
|
+
)
|
|
32610
|
+
}
|
|
32611
|
+
) : null,
|
|
32612
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Box, { style: { flex: "1 1 auto", minHeight: 0 }, children: renderContent() })
|
|
32613
|
+
] })
|
|
32225
32614
|
] })
|
|
32226
32615
|
}
|
|
32227
32616
|
);
|
|
@@ -33167,6 +33556,13 @@ function isEditable(el) {
|
|
|
33167
33556
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA") return true;
|
|
33168
33557
|
return el.isContentEditable;
|
|
33169
33558
|
}
|
|
33559
|
+
function setNativeValue(el, value) {
|
|
33560
|
+
var _a;
|
|
33561
|
+
const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
|
|
33562
|
+
const setter = (_a = Object.getOwnPropertyDescriptor(proto, "value")) == null ? void 0 : _a.set;
|
|
33563
|
+
if (setter) setter.call(el, value);
|
|
33564
|
+
else el.value = value;
|
|
33565
|
+
}
|
|
33170
33566
|
async function doCopy() {
|
|
33171
33567
|
var _a;
|
|
33172
33568
|
const text = (_a = window.getSelection()) == null ? void 0 : _a.toString();
|
|
@@ -33188,7 +33584,7 @@ async function doCut(el) {
|
|
|
33188
33584
|
} catch {
|
|
33189
33585
|
return false;
|
|
33190
33586
|
}
|
|
33191
|
-
el
|
|
33587
|
+
setNativeValue(el, el.value.slice(0, start) + el.value.slice(end));
|
|
33192
33588
|
el.selectionStart = el.selectionEnd = start;
|
|
33193
33589
|
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
33194
33590
|
return true;
|
|
@@ -33202,7 +33598,7 @@ async function doPaste(el) {
|
|
|
33202
33598
|
}
|
|
33203
33599
|
const start = el.selectionStart ?? el.value.length;
|
|
33204
33600
|
const end = el.selectionEnd ?? el.value.length;
|
|
33205
|
-
el
|
|
33601
|
+
setNativeValue(el, el.value.slice(0, start) + text + el.value.slice(end));
|
|
33206
33602
|
el.selectionStart = el.selectionEnd = start + text.length;
|
|
33207
33603
|
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
33208
33604
|
return true;
|
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",
|