@qodalis/vue-cli 2.0.0-beta.11 → 2.0.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -129,6 +129,7 @@ import {
129
129
  ref as ref2,
130
130
  computed,
131
131
  inject as inject2,
132
+ watch,
132
133
  h as h2,
133
134
  onMounted as onMounted2,
134
135
  onBeforeUnmount as onBeforeUnmount2
@@ -285,7 +286,7 @@ var CliPanel = defineComponent3({
285
286
  ],
286
287
  setup(props, { expose, emit }) {
287
288
  const config = inject2(CliConfigKey, null);
288
- const mergedOptions = computed(() => props.options ?? config?.options);
289
+ const mergedOptions = computed(() => props.options ? { ...config?.options, ...props.options } : config?.options);
289
290
  const mergedModules = computed(() => props.modules ?? config?.modules);
290
291
  const mergedProcessors = computed(() => props.processors ?? config?.processors);
291
292
  const mergedServices = computed(() => props.services ?? config?.services);
@@ -367,6 +368,107 @@ var CliPanel = defineComponent3({
367
368
  };
368
369
  const panelResizing = ref2(false);
369
370
  let panelResizeState = { startY: 0, startHeight: 0, startX: 0, startWidth: 0 };
371
+ const statusExecutionState = ref2("idle");
372
+ const statusLastCommand = ref2(null);
373
+ const statusServiceCount = ref2({ running: 0, total: 0 });
374
+ const statusServiceDetails = ref2([]);
375
+ const statusServerState = ref2("none");
376
+ const statusServerDetails = ref2([]);
377
+ const statusUptime = ref2(0);
378
+ const notification = ref2(null);
379
+ const servicesDropdownOpen = ref2(false);
380
+ const serversDropdownOpen = ref2(false);
381
+ const servicesDropdownTriggerRect = ref2(null);
382
+ const serversDropdownTriggerRect = ref2(null);
383
+ const formattedUptime = computed(() => {
384
+ const mins = Math.floor(statusUptime.value / 6e4);
385
+ if (mins < 60) return `${mins}m`;
386
+ const hrs = Math.floor(mins / 60);
387
+ return `${hrs}h${mins % 60}m`;
388
+ });
389
+ let execPollTimer;
390
+ let globalPollTimer;
391
+ function startStatusPolling() {
392
+ stopStatusPolling();
393
+ execPollTimer = setInterval(() => {
394
+ const tab = tabs.value.find((t) => t.id === resolvedActiveTabId.value);
395
+ if (!tab) return;
396
+ const engine = engineMap.get(tab.panes[0]?.id);
397
+ if (!engine) return;
398
+ const context = engine.getContext();
399
+ if (!context) return;
400
+ const running = !!context.isExecuting || !!context.contextProcessor;
401
+ statusExecutionState.value = running ? "running" : "idle";
402
+ const result = context.lastCommandResult;
403
+ statusLastCommand.value = result ? { name: result.command, success: result.success } : null;
404
+ const notif = context.notifier?.current;
405
+ notification.value = notif || null;
406
+ }, 300);
407
+ globalPollTimer = setInterval(() => {
408
+ const tab = tabs.value.find((t) => t.id === resolvedActiveTabId.value);
409
+ if (!tab) return;
410
+ const engine = engineMap.get(tab.panes[0]?.id);
411
+ if (!engine) return;
412
+ const context = engine.getContext();
413
+ if (!context) return;
414
+ try {
415
+ const services = context.backgroundServices?.list() ?? [];
416
+ statusServiceCount.value = { running: services.filter((s) => s.status === "running").length, total: services.length };
417
+ statusServiceDetails.value = services.map((s) => ({ name: s.name, status: s.status, description: s.description }));
418
+ } catch {
419
+ }
420
+ try {
421
+ const serverManager = context.services?.get?.("cli-server-manager");
422
+ const details = [];
423
+ if (serverManager?.connections?.size > 0) {
424
+ let anyConnected = false;
425
+ for (const [name, conn] of serverManager.connections) {
426
+ if (conn.connected) anyConnected = true;
427
+ details.push({
428
+ name,
429
+ url: conn.config?.url ?? "",
430
+ connected: !!conn.connected,
431
+ apiVersion: conn.connected ? conn.apiVersion : void 0,
432
+ commandCount: conn.connected ? conn.commands?.length : void 0
433
+ });
434
+ }
435
+ statusServerState.value = anyConnected ? "connected" : "disconnected";
436
+ } else {
437
+ const configuredServers = engine.options?.servers;
438
+ if (Array.isArray(configuredServers) && configuredServers.length > 0) {
439
+ for (const srv of configuredServers) {
440
+ if (srv.enabled === false) continue;
441
+ details.push({
442
+ name: srv.name,
443
+ url: srv.url ?? "",
444
+ connected: false
445
+ });
446
+ }
447
+ statusServerState.value = "disconnected";
448
+ } else {
449
+ statusServerState.value = "none";
450
+ }
451
+ }
452
+ statusServerDetails.value = details;
453
+ } catch {
454
+ }
455
+ statusUptime.value = engine.startedAt ? Date.now() - engine.startedAt : 0;
456
+ }, 2e3);
457
+ }
458
+ function stopStatusPolling() {
459
+ if (execPollTimer) {
460
+ clearInterval(execPollTimer);
461
+ execPollTimer = void 0;
462
+ }
463
+ if (globalPollTimer) {
464
+ clearInterval(globalPollTimer);
465
+ globalPollTimer = void 0;
466
+ }
467
+ }
468
+ watch(initialized, (val) => {
469
+ if (val) startStatusPolling();
470
+ else stopStatusPolling();
471
+ });
370
472
  function addTab(title) {
371
473
  const tabId = nextTabId++;
372
474
  const paneId = nextPaneId++;
@@ -443,6 +545,10 @@ var CliPanel = defineComponent3({
443
545
  tabs.value = tabs.value.map((t) => {
444
546
  if (t.id !== targetTabId) return t;
445
547
  const newPanes = [...t.panes, { id: paneId, widthPercent: 0 }];
548
+ const evenWidth = 100 / newPanes.length;
549
+ newPanes.forEach((p) => {
550
+ p.widthPercent = evenWidth;
551
+ });
446
552
  normalizePanes(newPanes);
447
553
  return { ...t, panes: newPanes };
448
554
  });
@@ -585,6 +691,7 @@ var CliPanel = defineComponent3({
585
691
  onBeforeUnmount2(() => {
586
692
  document.removeEventListener("mousemove", onPaneResizeMove);
587
693
  document.removeEventListener("mouseup", onPaneResizeEnd);
694
+ stopStatusPolling();
588
695
  });
589
696
  function toggleMaximize() {
590
697
  if (!resolvedMaximized.value) {
@@ -620,6 +727,8 @@ var CliPanel = defineComponent3({
620
727
  const positionDropdownOpen = ref2(false);
621
728
  function closePositionDropdown() {
622
729
  positionDropdownOpen.value = false;
730
+ servicesDropdownOpen.value = false;
731
+ serversDropdownOpen.value = false;
623
732
  }
624
733
  function togglePositionDropdown(e) {
625
734
  e.stopPropagation();
@@ -746,6 +855,105 @@ var CliPanel = defineComponent3({
746
855
  ]),
747
856
  "CLI"
748
857
  ]),
858
+ // Status indicators (bottom/top only)
859
+ resolvedPosition.value === "bottom" || resolvedPosition.value === "top" ? h2("div", { class: "cli-panel-status-indicators" }, [
860
+ // Execution state
861
+ h2("span", { class: ["cli-panel-status-item", statusExecutionState.value === "running" ? "status-running" : ""].filter(Boolean).join(" ") }, [
862
+ h2("span", { class: ["cli-panel-status-dot", statusExecutionState.value === "running" ? "dot-running" : "dot-idle"].join(" ") }),
863
+ h2("span", { class: "cli-panel-status-label" }, statusExecutionState.value)
864
+ ]),
865
+ // Background services
866
+ statusServiceCount.value.total > 0 ? h2("span", {
867
+ class: "cli-panel-status-item status-clickable",
868
+ onClick: (e) => {
869
+ e.stopPropagation();
870
+ servicesDropdownTriggerRect.value = e.currentTarget.getBoundingClientRect();
871
+ servicesDropdownOpen.value = !servicesDropdownOpen.value;
872
+ serversDropdownOpen.value = false;
873
+ }
874
+ }, [
875
+ h2("span", { class: "cli-panel-status-icon", innerHTML: "&#9881;" }),
876
+ h2("span", { class: "cli-panel-status-label" }, `${statusServiceCount.value.running}/${statusServiceCount.value.total} services`)
877
+ ]) : null,
878
+ // Last command
879
+ statusLastCommand.value ? h2("span", { class: "cli-panel-status-item" }, [
880
+ h2("span", { class: ["cli-panel-status-icon", statusLastCommand.value.success ? "status-success" : "status-error"].join(" "), innerHTML: statusLastCommand.value.success ? "&#10003;" : "&#10005;" }),
881
+ h2("span", { class: "cli-panel-status-label" }, statusLastCommand.value.name)
882
+ ]) : null,
883
+ // Server connection
884
+ statusServerState.value !== "none" ? h2("span", {
885
+ class: "cli-panel-status-item status-clickable",
886
+ onClick: (e) => {
887
+ e.stopPropagation();
888
+ serversDropdownTriggerRect.value = e.currentTarget.getBoundingClientRect();
889
+ serversDropdownOpen.value = !serversDropdownOpen.value;
890
+ servicesDropdownOpen.value = false;
891
+ }
892
+ }, [
893
+ h2("span", { class: ["cli-panel-status-dot", statusServerState.value === "connected" ? "dot-idle" : "dot-error"].join(" ") }),
894
+ h2("span", { class: "cli-panel-status-label" }, `${statusServerDetails.value.filter((s) => s.connected).length}/${statusServerDetails.value.length} servers`)
895
+ ]) : null,
896
+ // Uptime
897
+ statusUptime.value > 0 ? h2("span", { class: "cli-panel-status-item status-muted" }, [
898
+ h2("span", { class: "cli-panel-status-icon", innerHTML: "&uarr;" }),
899
+ h2("span", { class: "cli-panel-status-label" }, formattedUptime.value)
900
+ ]) : null,
901
+ // Custom notification
902
+ notification.value ? h2("span", { class: `cli-panel-status-item status-text level-${notification.value.level}` }, [
903
+ h2("span", { class: "cli-panel-status-label" }, notification.value.message)
904
+ ]) : null
905
+ ].filter(Boolean)) : null,
906
+ // Compact status indicators (left/right positions — CSS controls visibility)
907
+ h2("div", { class: "cli-panel-status-indicators-compact" }, [
908
+ // Execution state
909
+ h2("span", { class: "cli-panel-status-compact-item", title: statusExecutionState.value }, [
910
+ h2("span", { class: ["cli-panel-status-dot", statusExecutionState.value === "running" ? "dot-running" : "dot-idle"].join(" ") })
911
+ ]),
912
+ // Background services
913
+ statusServiceCount.value.total > 0 ? h2("span", {
914
+ class: "cli-panel-status-compact-item status-clickable",
915
+ title: `${statusServiceCount.value.running}/${statusServiceCount.value.total} services`,
916
+ onClick: (e) => {
917
+ e.stopPropagation();
918
+ servicesDropdownTriggerRect.value = e.currentTarget.getBoundingClientRect();
919
+ servicesDropdownOpen.value = !servicesDropdownOpen.value;
920
+ serversDropdownOpen.value = false;
921
+ }
922
+ }, [
923
+ h2("span", { class: "cli-panel-status-icon", innerHTML: "&#9881;" })
924
+ ]) : null,
925
+ // Last command
926
+ statusLastCommand.value ? h2("span", {
927
+ class: "cli-panel-status-compact-item",
928
+ title: `${statusLastCommand.value.success ? "\u2713" : "\u2717"} ${statusLastCommand.value.name}`
929
+ }, [
930
+ h2("span", {
931
+ class: ["cli-panel-status-icon", statusLastCommand.value.success ? "status-success" : "status-error"].join(" "),
932
+ innerHTML: statusLastCommand.value.success ? "&#10003;" : "&#10005;"
933
+ })
934
+ ]) : null,
935
+ // Server connection
936
+ statusServerState.value !== "none" ? h2("span", {
937
+ class: "cli-panel-status-compact-item status-clickable",
938
+ title: `${statusServerDetails.value.filter((s) => s.connected).length}/${statusServerDetails.value.length} servers`,
939
+ onClick: (e) => {
940
+ e.stopPropagation();
941
+ serversDropdownTriggerRect.value = e.currentTarget.getBoundingClientRect();
942
+ serversDropdownOpen.value = !serversDropdownOpen.value;
943
+ servicesDropdownOpen.value = false;
944
+ }
945
+ }, [
946
+ h2("span", { class: ["cli-panel-status-dot", statusServerState.value === "connected" ? "dot-idle" : "dot-error"].join(" ") })
947
+ ]) : null,
948
+ // Uptime
949
+ statusUptime.value > 0 ? h2("span", { class: "cli-panel-status-compact-item status-muted", title: formattedUptime.value }, [
950
+ h2("span", { class: "cli-panel-status-icon", innerHTML: "&uarr;" })
951
+ ]) : null,
952
+ // Notification
953
+ notification.value ? h2("span", { class: "cli-panel-status-compact-item", title: notification.value.message }, [
954
+ h2("span", { class: `cli-panel-status-compact-dot level-${notification.value.level}` })
955
+ ]) : null
956
+ ].filter(Boolean)),
749
957
  h2("div", { class: "cli-panel-action-buttons" }, [
750
958
  h2("div", {
751
959
  class: "cli-panel-btn-position-wrapper",
@@ -804,7 +1012,8 @@ var CliPanel = defineComponent3({
804
1012
  [closeIcon()]
805
1013
  ) : null
806
1014
  ])
807
- ])
1015
+ ]),
1016
+ h2("div", { class: ["cli-panel-glow-line", statusExecutionState.value === "running" ? "glow-active" : ""].filter(Boolean).join(" ") })
808
1017
  ]);
809
1018
  const contentEl = initialized.value ? h2("div", { class: "cli-panel-content", style: resolvedCollapsed.value ? { display: "none" } : void 0 }, [
810
1019
  // Tab bar
@@ -857,6 +1066,12 @@ var CliPanel = defineComponent3({
857
1066
  onDblclick: (e) => e.stopPropagation()
858
1067
  })
859
1068
  ] : [
1069
+ h2("span", { class: ["cli-panel-tab-dot", (() => {
1070
+ if (tab.id !== resolvedActiveTabId.value) return "dot-idle";
1071
+ if (statusExecutionState.value === "running") return "dot-running";
1072
+ if (statusLastCommand.value && !statusLastCommand.value.success) return "dot-error";
1073
+ return "dot-idle";
1074
+ })()].join(" ") }),
860
1075
  h2(
861
1076
  "span",
862
1077
  {
@@ -887,7 +1102,7 @@ var CliPanel = defineComponent3({
887
1102
  {
888
1103
  class: "cli-panel-add-tab",
889
1104
  title: "New terminal",
890
- onClick: addTab
1105
+ onClick: () => addTab()
891
1106
  },
892
1107
  "+"
893
1108
  )
@@ -1138,6 +1353,82 @@ var CliPanel = defineComponent3({
1138
1353
  h2("span", { class: "cli-panel-hide-tab-label" }, "CLI"),
1139
1354
  hideTabChevron(resolvedPosition.value)
1140
1355
  ]) : null;
1356
+ const servicesDropdownEl = servicesDropdownOpen.value && statusServiceCount.value.total > 0 ? h2("div", {
1357
+ class: "cli-panel-services-dropdown",
1358
+ style: (() => {
1359
+ const rect = servicesDropdownTriggerRect.value;
1360
+ if (!rect) return {};
1361
+ const base = { position: "fixed", zIndex: 1100 };
1362
+ switch (resolvedPosition.value) {
1363
+ case "top":
1364
+ return { ...base, top: `${rect.bottom + 4}px`, left: `${rect.left}px` };
1365
+ case "left":
1366
+ return { ...base, top: `${rect.top}px`, left: `${rect.right + 4}px` };
1367
+ case "right":
1368
+ return { ...base, top: `${rect.top}px`, right: `${window.innerWidth - rect.left + 4}px` };
1369
+ default:
1370
+ return { ...base, bottom: `${window.innerHeight - rect.top + 4}px`, left: `${rect.left}px` };
1371
+ }
1372
+ })(),
1373
+ onClick: (e) => e.stopPropagation()
1374
+ }, [
1375
+ h2("div", { class: "cli-panel-services-dropdown-header" }, "Background Services"),
1376
+ h2(
1377
+ "div",
1378
+ { class: "cli-panel-services-dropdown-list" },
1379
+ statusServiceDetails.value.map(
1380
+ (svc, i) => h2("div", { key: i, class: "cli-panel-services-dropdown-item" }, [
1381
+ h2("span", { class: ["cli-panel-svc-dot", svc.status === "running" ? "svc-running" : "svc-stopped"].join(" ") }),
1382
+ h2("div", { class: "cli-panel-svc-info" }, [
1383
+ h2("span", { class: "cli-panel-svc-name" }, svc.name),
1384
+ svc.description ? h2("span", { class: "cli-panel-svc-desc" }, svc.description) : null
1385
+ ].filter(Boolean)),
1386
+ h2("span", { class: "cli-panel-svc-status" }, svc.status)
1387
+ ])
1388
+ )
1389
+ ),
1390
+ statusServiceDetails.value.length === 0 ? h2("div", { class: "cli-panel-services-dropdown-empty" }, "No services registered") : null
1391
+ ].filter(Boolean)) : null;
1392
+ const serversDropdownEl = serversDropdownOpen.value && statusServerState.value !== "none" ? h2("div", {
1393
+ class: "cli-panel-services-dropdown",
1394
+ style: (() => {
1395
+ const rect = serversDropdownTriggerRect.value;
1396
+ if (!rect) return {};
1397
+ const base = { position: "fixed", zIndex: 1100 };
1398
+ switch (resolvedPosition.value) {
1399
+ case "top":
1400
+ return { ...base, top: `${rect.bottom + 4}px`, left: `${rect.left}px` };
1401
+ case "left":
1402
+ return { ...base, top: `${rect.top}px`, left: `${rect.right + 4}px` };
1403
+ case "right":
1404
+ return { ...base, top: `${rect.top}px`, right: `${window.innerWidth - rect.left + 4}px` };
1405
+ default:
1406
+ return { ...base, bottom: `${window.innerHeight - rect.top + 4}px`, left: `${rect.left}px` };
1407
+ }
1408
+ })(),
1409
+ onClick: (e) => e.stopPropagation()
1410
+ }, [
1411
+ h2("div", { class: "cli-panel-services-dropdown-header" }, "Server Connections"),
1412
+ h2(
1413
+ "div",
1414
+ { class: "cli-panel-services-dropdown-list" },
1415
+ statusServerDetails.value.map(
1416
+ (srv, i) => h2("div", { key: i, class: "cli-panel-services-dropdown-item" }, [
1417
+ h2("span", { class: ["cli-panel-svc-dot", srv.connected ? "svc-running" : "svc-stopped"].join(" ") }),
1418
+ h2("div", { class: "cli-panel-svc-info" }, [
1419
+ h2("span", { class: "cli-panel-svc-name" }, srv.name),
1420
+ srv.url ? h2("span", { class: "cli-panel-svc-desc" }, srv.url) : null
1421
+ ].filter(Boolean)),
1422
+ h2("div", { class: "cli-panel-srv-meta" }, [
1423
+ h2("span", { class: "cli-panel-svc-status" }, srv.connected ? "connected" : "disconnected"),
1424
+ srv.apiVersion ? h2("span", { class: "cli-panel-svc-desc" }, `v${srv.apiVersion}`) : null,
1425
+ srv.commandCount ? h2("span", { class: "cli-panel-svc-desc" }, `${srv.commandCount} cmds`) : null
1426
+ ].filter(Boolean))
1427
+ ])
1428
+ )
1429
+ ),
1430
+ statusServerDetails.value.length === 0 ? h2("div", { class: "cli-panel-services-dropdown-empty" }, "No servers configured") : null
1431
+ ].filter(Boolean)) : null;
1141
1432
  return h2("div", {}, [
1142
1433
  hideTabEl,
1143
1434
  h2(
@@ -1152,7 +1443,9 @@ var CliPanel = defineComponent3({
1152
1443
  },
1153
1444
  [headerEl, contentEl]
1154
1445
  ),
1155
- contextMenuEl
1446
+ contextMenuEl,
1447
+ servicesDropdownEl,
1448
+ serversDropdownEl
1156
1449
  ]);
1157
1450
  };
1158
1451
  }