@64mb/freelens-power 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/out/main/ai-ipc.js +34 -3
- package/out/main/ai-ipc.js.map +1 -1
- package/out/main/common/power-logs-limits.js +227 -0
- package/out/main/common/power-logs-limits.js.map +1 -0
- package/out/main/common/power-logs.js +32 -0
- package/out/main/common/power-logs.js.map +1 -0
- package/out/main/common/resource-search.js +61 -0
- package/out/main/common/resource-search.js.map +1 -0
- package/out/main/common/store/logs-preferences-store.js +45 -0
- package/out/main/common/store/logs-preferences-store.js.map +1 -0
- package/out/main/common/store/monitoring-preferences-store.js +5 -0
- package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/main/dashboard-icon-cache.js +1 -1
- package/out/main/index.js +6 -0
- package/out/main/index.js.map +1 -1
- package/out/main/power-logs-budget.js +126 -0
- package/out/main/power-logs-budget.js.map +1 -0
- package/out/main/power-logs-child.js +86 -0
- package/out/main/power-logs-child.js.map +1 -0
- package/out/main/power-logs-database.js +179 -0
- package/out/main/power-logs-database.js.map +1 -0
- package/out/main/power-logs-ipc.js +275 -0
- package/out/main/power-logs-ipc.js.map +1 -0
- package/out/main/power-logs-query-child.js +23 -0
- package/out/main/power-logs-query-child.js.map +1 -0
- package/out/main/power-logs-query.js +127 -0
- package/out/main/power-logs-query.js.map +1 -0
- package/out/main/power-logs-worker.js +215 -0
- package/out/main/power-logs-worker.js.map +1 -0
- package/out/main/resource-search-database.js +209 -0
- package/out/main/resource-search-database.js.map +1 -0
- package/out/main/resource-search-worker.js +56 -0
- package/out/main/resource-search-worker.js.map +1 -0
- package/out/main/resource-search.js +155 -0
- package/out/main/resource-search.js.map +1 -0
- package/out/renderer/ai-logs-sql.js +27 -0
- package/out/renderer/ai-logs-sql.js.map +1 -0
- package/out/renderer/ai-message.js +48 -27
- package/out/renderer/ai-message.js.map +1 -1
- package/out/renderer/ai-terminal-context.js +50 -40
- package/out/renderer/ai-terminal-context.js.map +1 -1
- package/out/renderer/ai.js +15 -2
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/appearance.js +2 -1
- package/out/renderer/appearance.js.map +1 -1
- package/out/renderer/gateway-relationships-client.js +107 -0
- package/out/renderer/gateway-relationships-client.js.map +1 -0
- package/out/renderer/index.js +67 -29
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/power-log-json.js +29 -0
- package/out/renderer/power-log-json.js.map +1 -0
- package/out/renderer/power-logs-client.js +35 -0
- package/out/renderer/power-logs-client.js.map +1 -0
- package/out/renderer/power-logs-collector.js +316 -0
- package/out/renderer/power-logs-collector.js.map +1 -0
- package/out/renderer/power-logs-entrypoints.js +201 -0
- package/out/renderer/power-logs-entrypoints.js.map +1 -0
- package/out/renderer/power-logs-sql-row.js +52 -0
- package/out/renderer/power-logs-sql-row.js.map +1 -0
- package/out/renderer/power-logs-transport.js +122 -0
- package/out/renderer/power-logs-transport.js.map +1 -0
- package/out/renderer/power-logs.css.js +116 -0
- package/out/renderer/power-logs.css.js.map +1 -0
- package/out/renderer/power-logs.js +1352 -0
- package/out/renderer/power-logs.js.map +1 -0
- package/out/renderer/preferences/logs-preferences.js +93 -0
- package/out/renderer/preferences/logs-preferences.js.map +1 -0
- package/out/renderer/preferences/monitoring-preferences.js +10 -0
- package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
- package/out/renderer/preferences/preferences.js +24 -10
- package/out/renderer/preferences/preferences.js.map +1 -1
- package/out/renderer/resource-relationships.css.js +1 -1
- package/out/renderer/resource-relationships.css.js.map +1 -1
- package/out/renderer/resource-relationships.js +46 -8
- package/out/renderer/resource-relationships.js.map +1 -1
- package/out/renderer/resource-search-client.js +116 -0
- package/out/renderer/resource-search-client.js.map +1 -0
- package/out/renderer/resource-search-discovery.js +79 -0
- package/out/renderer/resource-search-discovery.js.map +1 -0
- package/out/renderer/resource-search-model.js +2 -1
- package/out/renderer/resource-search-model.js.map +1 -1
- package/out/renderer/resource-search-routing.js +78 -0
- package/out/renderer/resource-search-routing.js.map +1 -0
- package/out/renderer/resource-search-sync.js +199 -0
- package/out/renderer/resource-search-sync.js.map +1 -0
- package/out/renderer/resource-search.js +279 -54
- package/out/renderer/resource-search.js.map +1 -1
- package/out/renderer/src/common/gateway-relationships.js +122 -0
- package/out/renderer/src/common/gateway-relationships.js.map +1 -0
- package/out/renderer/src/common/power-log-parser.js +114 -0
- package/out/renderer/src/common/power-log-parser.js.map +1 -0
- package/out/renderer/src/common/power-logs-ai.js +56 -0
- package/out/renderer/src/common/power-logs-ai.js.map +1 -0
- package/out/renderer/src/common/power-logs-limits.js +227 -0
- package/out/renderer/src/common/power-logs-limits.js.map +1 -0
- package/out/renderer/src/common/power-logs.js +32 -0
- package/out/renderer/src/common/power-logs.js.map +1 -0
- package/out/renderer/src/common/resource-relationships.js +8 -0
- package/out/renderer/src/common/resource-relationships.js.map +1 -1
- package/out/renderer/src/common/resource-search.js +6 -0
- package/out/renderer/src/common/resource-search.js.map +1 -0
- package/out/renderer/src/common/store/logs-preferences-store.js +45 -0
- package/out/renderer/src/common/store/logs-preferences-store.js.map +1 -0
- package/out/renderer/src/common/store/monitoring-preferences-store.js +5 -0
- package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -12,15 +12,18 @@ Power tools and personal dashboards for Freelens. Built for Freelens 1.x and tes
|
|
|
12
12
|
- **Power Dashboard:** reorderable XS/S/M/L/XL website cards in a responsive grid, cached pages, loading skeletons, interactive element selection, expansion, pinned floating windows, shared website sessions, per-card 10-second refresh including pinned windows, and optional background refresh
|
|
13
13
|
- **Monitoring:** optional CPU and memory trends, allocation rings, pinned tooltips, and node/pod charts using metrics-server and Kubernetes APIs
|
|
14
14
|
- **Resource diagnostics:** CPU/memory consumers, grouped warning timelines, Pending and Not ready triage, Service/HPA checks, operational resource and namespace summaries, scoped AI handoff, and incident-summary copying
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
15
|
+
- **Power Logs:** opt-in colored workload logs with structured fields, source and level filters, bounded live collection, temporary SQLite captures, cancellable read-only SQL, compact density, configurable limits, NDJSON export and reviewable AI context with SQL drafts; native Pod logs remain available
|
|
16
|
+
- **Resource relationships:** a focused Service graph connects Ingress and installed Gateway API routes/listeners to selected Pods, published endpoints, owners and node references, with acceptance and cross-namespace reference evidence, resource links and saved upstream visibility
|
|
17
|
+
- **Fast resource search:** double Shift searches all discoverable resource types, including Secrets, ConfigMaps and custom resources, through a persistent local metadata index with gentle background refresh, type and namespace filters, name-part and typo matching, resource links and explicit AI attachment; search and background indexing can be disabled together in Monitoring settings
|
|
17
18
|
- **Local metric history:** opt-in SQLite storage, up to seven days within a 100 MiB budget, with aggregated ranges and explicit collection gaps
|
|
18
19
|
- **AI assistant:** native Codex or Claude CLI, per-cluster conversations, read-only API discovery and resource summaries, model/effort/speed selection, editable prompts, quick-start commands, Markdown, cancellable replies, context preview, optional terminal attachments, resource links, resizable pinned chat, and a switch to disable all AI features
|
|
19
20
|
- **Read-only UI:** hides common mutation actions without changing Kubernetes permissions
|
|
20
21
|
- **Master switch:** restores the native interface while preserving all settings
|
|
21
22
|
- **Settings:** native switches, compact dashboard editors, and JSON backup and restore of cards and prompt shortcuts
|
|
22
23
|
|
|
23
|
-
AI tool results exclude environment values and Secret payloads;
|
|
24
|
+
AI tool results exclude environment values and Secret payloads; automatic log summaries contain numeric issue counters. Power Logs lines and SQL results attach to a reviewable context block when the AI action is clicked. Drafted SQL is inserted into the editor without execution. Terminal output is sent only when explicitly attached; review its masked preview before sending. Websites run in isolated Electron views. Every dashboard card also opens in your browser.
|
|
25
|
+
|
|
26
|
+
Power Logs captures stay on the local disk for one hour by default, with configurable retention, and are removed when the feature stops. Collection follows current Kubernetes permissions and retained container logs. Large workloads use rotating bounded tails, so busy sources can have gaps; coverage and partial captures are reported in the interface.
|
|
24
27
|
|
|
25
28
|
Monitoring history is collected while Freelens is running and the cluster view is active. Cluster and node series are retained automatically when enabled. History cannot backfill periods without collection. Timelines combine retained Kubernetes events with changes observed while the diagnostics page is open. Local Pending checks explain available evidence and do not reproduce the full scheduler.
|
|
26
29
|
|
|
@@ -56,7 +59,7 @@ Use `pnpm dev` to rebuild on changes, then reinstall the package.
|
|
|
56
59
|
|
|
57
60
|
## CI and releases
|
|
58
61
|
|
|
59
|
-
Pull requests and pushes to `main` run lint, type checking, unit tests, and a
|
|
62
|
+
Pull requests and pushes to `main` run independent lint, type checking, unit tests, build and real Freelens UI checks against a disposable kind cluster. Scheduled checks add a light/narrow profile, restart and index refresh scenarios. See [UI testing](e2e/README.md) for fixtures, screenshots and coverage limits.
|
|
60
63
|
|
|
61
64
|
Run **Make Release** in GitHub Actions to create a version bump pull request. Merging it publishes the package to npm and the installable `.tgz` archive in [GitHub Releases](https://github.com/64mb/freelens-power/releases). Use **Package Release** with the merged pull request number to retry a failed release.
|
|
62
65
|
|
package/out/main/ai-ipc.js
CHANGED
|
@@ -6,6 +6,8 @@ const require_ai = require("./common/ai.js");
|
|
|
6
6
|
const require_ai_resources = require("./ai-resources.js");
|
|
7
7
|
const require_ai$1 = require("./ai.js");
|
|
8
8
|
const require_ai_discovery = require("./ai-discovery.js");
|
|
9
|
+
const require_power_logs_budget = require("./power-logs-budget.js");
|
|
10
|
+
let node_crypto = require("node:crypto");
|
|
9
11
|
let electron = require("electron");
|
|
10
12
|
//#region src/main/ai-ipc.ts
|
|
11
13
|
function trusted(event) {
|
|
@@ -59,9 +61,38 @@ function startAiIpc() {
|
|
|
59
61
|
return require_ai_discovery.discoverAiResources((path) => api.get(path, void 0, { signal }), signal);
|
|
60
62
|
},
|
|
61
63
|
readLogs: async (query, signal) => {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
const streamId = (0, node_crypto.randomUUID)();
|
|
65
|
+
const controller = new AbortController();
|
|
66
|
+
const abort = () => controller.abort();
|
|
67
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
68
|
+
if (signal?.aborted) abort();
|
|
69
|
+
const timeout = setTimeout(abort, 3e4);
|
|
70
|
+
let renewal;
|
|
71
|
+
try {
|
|
72
|
+
await require_power_logs_budget.acquirePowerLogStream(id, streamId, false, controller.signal);
|
|
73
|
+
renewal = setInterval(() => {
|
|
74
|
+
try {
|
|
75
|
+
require_power_logs_budget.renewPowerLogStream(id, streamId);
|
|
76
|
+
} catch {
|
|
77
|
+
abort();
|
|
78
|
+
}
|
|
79
|
+
}, 1e4);
|
|
80
|
+
await require_power_logs_budget.requestPowerLogPermit(id, void 0, controller.signal);
|
|
81
|
+
if (controller.signal.aborted) throw new Error("AI request canceled");
|
|
82
|
+
const response = await require_extensions.Main.K8sApi.KubeJsonApi.forCluster.call(void 0, id).getResponse(query.path, { query: query.query }, {
|
|
83
|
+
signal: controller.signal,
|
|
84
|
+
size: 65536
|
|
85
|
+
});
|
|
86
|
+
if (!response.ok) throw new Error("Log summary is unavailable");
|
|
87
|
+
const text = await response.text();
|
|
88
|
+
if (text.length) await require_power_logs_budget.requestPowerLogPermit(id, Buffer.byteLength(text), controller.signal);
|
|
89
|
+
return text;
|
|
90
|
+
} finally {
|
|
91
|
+
clearTimeout(timeout);
|
|
92
|
+
clearInterval(renewal);
|
|
93
|
+
signal?.removeEventListener("abort", abort);
|
|
94
|
+
require_power_logs_budget.releasePowerLogStream(id, streamId);
|
|
95
|
+
}
|
|
65
96
|
},
|
|
66
97
|
read: async (query) => {
|
|
67
98
|
if (controller.signal.aborted) throw new Error("AI request canceled");
|
package/out/main/ai-ipc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-ipc.js","names":[],"sources":["../../src/main/ai-ipc.ts"],"sourcesContent":["import { Common, Main } from \"@freelensapp/extensions\";\nimport { BrowserWindow, type IpcMainInvokeEvent, ipcMain } from \"electron\";\nimport { reaction } from \"mobx\";\nimport { AI_CHAT_CHANNEL, AI_READ_ACTIVITY_CHANNEL, type AiChatRequest, validAiRequestId } from \"../common/ai\";\nimport { AI_CANCEL_CHANNEL } from \"../common/ai-extras\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { aiFailureCode, runAiChat } from \"./ai\";\nimport { discoverAiResources } from \"./ai-discovery\";\nimport { aiReadPath } from \"./ai-resources\";\n\nfunction trusted(event: IpcMainInvokeEvent): boolean {\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window || window.isDestroyed()) return false;\n try {\n const url = new URL(event.senderFrame?.url ?? \"\");\n return (\n url.protocol === \"https:\" &&\n (url.hostname === \"renderer.freelens.app\" || url.hostname.endsWith(\".renderer.freelens.app\"))\n );\n } catch {\n return false;\n }\n}\n\nexport function startAiIpc(): () => void {\n const pending = new Map<number, AbortController>();\n const origins = new Map<number, { requestId?: string; frame: IpcMainInvokeEvent[\"senderFrame\"]; url?: string }>();\n const abortAll = () => {\n for (const controller of pending.values()) controller.abort();\n };\n const stop = reaction(\n () => AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>().enabled,\n (enabled) => {\n if (!enabled) abortAll();\n },\n );\n ipcMain.handle(AI_CHAT_CHANNEL, async (event, request: AiChatRequest) => {\n const preferences = AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>();\n if (!trusted(event) || !preferences.enabled) throw new Error(\"AI assistant is disabled or unavailable\");\n if (request?.requestId !== undefined && !validAiRequestId(request.requestId))\n throw new Error(\"Invalid AI request identifier\");\n const frame = event.senderFrame;\n const frameUrl = frame?.url;\n if (pending.has(event.sender.id)) throw new Error(\"An AI request is already running\");\n const controller = new AbortController();\n pending.set(event.sender.id, controller);\n origins.set(event.sender.id, { requestId: request.requestId, frame, url: frameUrl });\n const abort = () => controller.abort();\n event.sender.once(\"destroyed\", abort);\n try {\n const response = await runAiChat(\n {\n ...request,\n provider: preferences.provider ?? \"codex\",\n model: preferences.provider === \"claude\" ? preferences.claudeModel : preferences.model,\n speed: preferences.provider === \"claude\" ? \"default\" : preferences.speed,\n reasoningEffort: preferences.provider === \"claude\" ? \"\" : preferences.reasoningEffort,\n systemPrompt: [preferences.systemPrompt, request?.context?.clusterId ? preferences.clusterPrompt : \"\"]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n },\n (id) => {\n const cluster = Main.Catalog.getClusterById(id);\n if (!cluster) throw new Error(\"Select a registered cluster first\");\n return {\n discover: async (signal) => {\n const api = Main.K8sApi.KubeJsonApi.forCluster.call(undefined, id);\n return discoverAiResources((path) => api.get(path, undefined, { signal }), signal);\n },\n readLogs: async (query, signal) => {\n // the host exposes [forCluster] through a non-callable legacy proxy whose methods remain callable\n const response = await Main.K8sApi.KubeJsonApi.forCluster\n .call(undefined, id)\n .getResponse(query.path, { query: query.query }, { signal });\n if (!response.ok) throw new Error(\"Log summary is unavailable\");\n return response.text();\n },\n read: async (query) => {\n if (controller.signal.aborted) throw new Error(\"AI request canceled\");\n if (query.resource) {\n const api = Main.K8sApi.KubeJsonApi.forCluster.call(undefined, id);\n return api.get(aiReadPath(query), undefined, { signal: controller.signal });\n }\n return query.name\n ? Main.K8s.getResource(id, { ...query, name: query.name })\n : { items: await Main.K8s.queryCluster(id, query) };\n },\n };\n },\n controller.signal,\n (activity) => {\n if (\n !request.requestId ||\n controller.signal.aborted ||\n pending.get(event.sender.id) !== controller ||\n !preferences.enabled ||\n !frame ||\n frame.detached ||\n frame.url !== frameUrl ||\n !trusted(event)\n )\n return;\n try {\n frame.send(AI_READ_ACTIVITY_CHANNEL, { requestId: request.requestId, ...activity });\n } catch {\n /* the originating frame may have closed */\n }\n },\n );\n controller.signal.throwIfAborted();\n return response;\n } catch (failure) {\n const code = aiFailureCode(failure);\n Common.logger.warn(\"[Freelens Power AI] request failed\", { code });\n throw new Error(`FREELENS_AI_${code}`);\n } finally {\n event.sender.removeListener(\"destroyed\", abort);\n pending.delete(event.sender.id);\n origins.delete(event.sender.id);\n }\n });\n ipcMain.handle(AI_CANCEL_CHANNEL, (event, requestId: unknown) => {\n if (!trusted(event) || !validAiRequestId(requestId)) return false;\n const origin = origins.get(event.sender.id);\n if (\n !origin ||\n origin.requestId !== requestId ||\n origin.frame !== event.senderFrame ||\n !origin.frame ||\n origin.frame.detached ||\n origin.frame.url !== origin.url\n )\n return false;\n pending.get(event.sender.id)?.abort();\n return true;\n });\n return () => {\n stop();\n abortAll();\n ipcMain.removeHandler(AI_CHAT_CHANNEL);\n ipcMain.removeHandler(AI_CANCEL_CHANNEL);\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-ipc.js","names":[],"sources":["../../src/main/ai-ipc.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { Common, Main } from \"@freelensapp/extensions\";\nimport { BrowserWindow, type IpcMainInvokeEvent, ipcMain } from \"electron\";\nimport { reaction } from \"mobx\";\nimport { AI_CHAT_CHANNEL, AI_READ_ACTIVITY_CHANNEL, type AiChatRequest, validAiRequestId } from \"../common/ai\";\nimport { AI_CANCEL_CHANNEL } from \"../common/ai-extras\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { aiFailureCode, runAiChat } from \"./ai\";\nimport { discoverAiResources } from \"./ai-discovery\";\nimport { aiReadPath } from \"./ai-resources\";\nimport {\n acquirePowerLogStream,\n releasePowerLogStream,\n renewPowerLogStream,\n requestPowerLogPermit,\n} from \"./power-logs-budget\";\n\nfunction trusted(event: IpcMainInvokeEvent): boolean {\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window || window.isDestroyed()) return false;\n try {\n const url = new URL(event.senderFrame?.url ?? \"\");\n return (\n url.protocol === \"https:\" &&\n (url.hostname === \"renderer.freelens.app\" || url.hostname.endsWith(\".renderer.freelens.app\"))\n );\n } catch {\n return false;\n }\n}\n\nexport function startAiIpc(): () => void {\n const pending = new Map<number, AbortController>();\n const origins = new Map<number, { requestId?: string; frame: IpcMainInvokeEvent[\"senderFrame\"]; url?: string }>();\n const abortAll = () => {\n for (const controller of pending.values()) controller.abort();\n };\n const stop = reaction(\n () => AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>().enabled,\n (enabled) => {\n if (!enabled) abortAll();\n },\n );\n ipcMain.handle(AI_CHAT_CHANNEL, async (event, request: AiChatRequest) => {\n const preferences = AiPreferencesStore.getInstanceOrCreate<AiPreferencesStore>();\n if (!trusted(event) || !preferences.enabled) throw new Error(\"AI assistant is disabled or unavailable\");\n if (request?.requestId !== undefined && !validAiRequestId(request.requestId))\n throw new Error(\"Invalid AI request identifier\");\n const frame = event.senderFrame;\n const frameUrl = frame?.url;\n if (pending.has(event.sender.id)) throw new Error(\"An AI request is already running\");\n const controller = new AbortController();\n pending.set(event.sender.id, controller);\n origins.set(event.sender.id, { requestId: request.requestId, frame, url: frameUrl });\n const abort = () => controller.abort();\n event.sender.once(\"destroyed\", abort);\n try {\n const response = await runAiChat(\n {\n ...request,\n provider: preferences.provider ?? \"codex\",\n model: preferences.provider === \"claude\" ? preferences.claudeModel : preferences.model,\n speed: preferences.provider === \"claude\" ? \"default\" : preferences.speed,\n reasoningEffort: preferences.provider === \"claude\" ? \"\" : preferences.reasoningEffort,\n systemPrompt: [preferences.systemPrompt, request?.context?.clusterId ? preferences.clusterPrompt : \"\"]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n },\n (id) => {\n const cluster = Main.Catalog.getClusterById(id);\n if (!cluster) throw new Error(\"Select a registered cluster first\");\n return {\n discover: async (signal) => {\n const api = Main.K8sApi.KubeJsonApi.forCluster.call(undefined, id);\n return discoverAiResources((path) => api.get(path, undefined, { signal }), signal);\n },\n readLogs: async (query, signal) => {\n const streamId = randomUUID();\n const controller = new AbortController();\n const abort = () => controller.abort();\n signal?.addEventListener(\"abort\", abort, { once: true });\n if (signal?.aborted) abort();\n const timeout = setTimeout(abort, 30000);\n let renewal: ReturnType<typeof setInterval> | undefined;\n try {\n await acquirePowerLogStream(id, streamId, false, controller.signal);\n renewal = setInterval(() => {\n try {\n renewPowerLogStream(id, streamId);\n } catch {\n abort();\n }\n }, 10000);\n await requestPowerLogPermit(id, undefined, controller.signal);\n if (controller.signal.aborted) throw new Error(\"AI request canceled\");\n // the host exposes [forCluster] through a non-callable legacy proxy whose methods remain callable\n const response = await Main.K8sApi.KubeJsonApi.forCluster\n .call(undefined, id)\n .getResponse(query.path, { query: query.query }, { signal: controller.signal, size: 65536 });\n if (!response.ok) throw new Error(\"Log summary is unavailable\");\n const text = await response.text();\n if (text.length) await requestPowerLogPermit(id, Buffer.byteLength(text), controller.signal);\n return text;\n } finally {\n clearTimeout(timeout);\n clearInterval(renewal);\n signal?.removeEventListener(\"abort\", abort);\n releasePowerLogStream(id, streamId);\n }\n },\n read: async (query) => {\n if (controller.signal.aborted) throw new Error(\"AI request canceled\");\n if (query.resource) {\n const api = Main.K8sApi.KubeJsonApi.forCluster.call(undefined, id);\n return api.get(aiReadPath(query), undefined, { signal: controller.signal });\n }\n return query.name\n ? Main.K8s.getResource(id, { ...query, name: query.name })\n : { items: await Main.K8s.queryCluster(id, query) };\n },\n };\n },\n controller.signal,\n (activity) => {\n if (\n !request.requestId ||\n controller.signal.aborted ||\n pending.get(event.sender.id) !== controller ||\n !preferences.enabled ||\n !frame ||\n frame.detached ||\n frame.url !== frameUrl ||\n !trusted(event)\n )\n return;\n try {\n frame.send(AI_READ_ACTIVITY_CHANNEL, { requestId: request.requestId, ...activity });\n } catch {\n /* the originating frame may have closed */\n }\n },\n );\n controller.signal.throwIfAborted();\n return response;\n } catch (failure) {\n const code = aiFailureCode(failure);\n Common.logger.warn(\"[Freelens Power AI] request failed\", { code });\n throw new Error(`FREELENS_AI_${code}`);\n } finally {\n event.sender.removeListener(\"destroyed\", abort);\n pending.delete(event.sender.id);\n origins.delete(event.sender.id);\n }\n });\n ipcMain.handle(AI_CANCEL_CHANNEL, (event, requestId: unknown) => {\n if (!trusted(event) || !validAiRequestId(requestId)) return false;\n const origin = origins.get(event.sender.id);\n if (\n !origin ||\n origin.requestId !== requestId ||\n origin.frame !== event.senderFrame ||\n !origin.frame ||\n origin.frame.detached ||\n origin.frame.url !== origin.url\n )\n return false;\n pending.get(event.sender.id)?.abort();\n return true;\n });\n return () => {\n stop();\n abortAll();\n ipcMain.removeHandler(AI_CHAT_CHANNEL);\n ipcMain.removeHandler(AI_CANCEL_CHANNEL);\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
const require_power_logs = require("./power-logs.js");
|
|
2
|
+
//#region src/common/power-logs-limits.ts
|
|
3
|
+
var KiB = 1024;
|
|
4
|
+
var MiB = KiB * KiB;
|
|
5
|
+
var LOG_LIMIT_FIELDS = [
|
|
6
|
+
{
|
|
7
|
+
key: "liveRows",
|
|
8
|
+
label: "Buffered rows",
|
|
9
|
+
unit: "rows",
|
|
10
|
+
group: "Live logs",
|
|
11
|
+
min: 1,
|
|
12
|
+
max: 1e6,
|
|
13
|
+
step: 1e3
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
key: "liveBytes",
|
|
17
|
+
label: "Buffer size",
|
|
18
|
+
unit: "MiB",
|
|
19
|
+
group: "Live logs",
|
|
20
|
+
min: KiB,
|
|
21
|
+
max: 1024 * MiB,
|
|
22
|
+
step: MiB,
|
|
23
|
+
scale: MiB
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
key: "batchRows",
|
|
27
|
+
label: "Batch rows",
|
|
28
|
+
unit: "rows",
|
|
29
|
+
group: "Live logs",
|
|
30
|
+
min: 1,
|
|
31
|
+
max: 1e5,
|
|
32
|
+
step: 100
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: "batchBytes",
|
|
36
|
+
label: "Batch size",
|
|
37
|
+
unit: "MiB",
|
|
38
|
+
group: "Live logs",
|
|
39
|
+
min: KiB,
|
|
40
|
+
max: 64 * MiB,
|
|
41
|
+
step: MiB,
|
|
42
|
+
scale: MiB
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
key: "recordBytes",
|
|
46
|
+
label: "Record size",
|
|
47
|
+
unit: "KiB",
|
|
48
|
+
group: "Live logs",
|
|
49
|
+
min: KiB,
|
|
50
|
+
max: 16 * MiB,
|
|
51
|
+
step: KiB,
|
|
52
|
+
scale: KiB
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
key: "historyLines",
|
|
56
|
+
label: "Lines per source",
|
|
57
|
+
unit: "lines",
|
|
58
|
+
group: "History",
|
|
59
|
+
min: 1,
|
|
60
|
+
max: 1e6,
|
|
61
|
+
step: 1e3
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: "historyBytes",
|
|
65
|
+
label: "Bytes per source",
|
|
66
|
+
unit: "MiB",
|
|
67
|
+
group: "History",
|
|
68
|
+
min: KiB,
|
|
69
|
+
max: 256 * MiB,
|
|
70
|
+
step: MiB,
|
|
71
|
+
scale: MiB
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
key: "historyConcurrency",
|
|
75
|
+
label: "Parallel requests",
|
|
76
|
+
unit: "requests",
|
|
77
|
+
group: "History",
|
|
78
|
+
min: 1,
|
|
79
|
+
max: 32,
|
|
80
|
+
step: 1
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
key: "captureBytes",
|
|
84
|
+
label: "Capture size",
|
|
85
|
+
unit: "MiB",
|
|
86
|
+
group: "Captures",
|
|
87
|
+
min: KiB,
|
|
88
|
+
max: 4096 * MiB,
|
|
89
|
+
step: MiB,
|
|
90
|
+
scale: MiB
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
key: "captureRows",
|
|
94
|
+
label: "Rows per capture",
|
|
95
|
+
unit: "rows",
|
|
96
|
+
group: "Captures",
|
|
97
|
+
min: 1,
|
|
98
|
+
max: 1e7,
|
|
99
|
+
step: 1e4
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
key: "captures",
|
|
103
|
+
label: "Retained captures",
|
|
104
|
+
unit: "captures",
|
|
105
|
+
group: "Captures",
|
|
106
|
+
min: 1,
|
|
107
|
+
max: 100,
|
|
108
|
+
step: 1
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
key: "sources",
|
|
112
|
+
label: "Sources per capture",
|
|
113
|
+
unit: "sources",
|
|
114
|
+
group: "Captures",
|
|
115
|
+
min: 1,
|
|
116
|
+
max: 2e3,
|
|
117
|
+
step: 10
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
key: "captureSourceLines",
|
|
121
|
+
label: "Lines per source",
|
|
122
|
+
unit: "lines",
|
|
123
|
+
group: "Captures",
|
|
124
|
+
min: 1,
|
|
125
|
+
max: 1e6,
|
|
126
|
+
step: 1e3
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
key: "captureSourceBytes",
|
|
130
|
+
label: "Bytes per source",
|
|
131
|
+
unit: "MiB",
|
|
132
|
+
group: "Captures",
|
|
133
|
+
min: KiB,
|
|
134
|
+
max: 256 * MiB,
|
|
135
|
+
step: MiB,
|
|
136
|
+
scale: MiB
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
key: "ttlMs",
|
|
140
|
+
label: "Retention",
|
|
141
|
+
unit: "minutes",
|
|
142
|
+
group: "Captures",
|
|
143
|
+
min: 6e4,
|
|
144
|
+
max: 10080 * 6e4,
|
|
145
|
+
step: 6e4,
|
|
146
|
+
scale: 6e4
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
key: "resultRows",
|
|
150
|
+
label: "Result rows",
|
|
151
|
+
unit: "rows",
|
|
152
|
+
group: "SQL results",
|
|
153
|
+
min: 1,
|
|
154
|
+
max: 1e5,
|
|
155
|
+
step: 100
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
key: "resultBytes",
|
|
159
|
+
label: "Result size",
|
|
160
|
+
unit: "MiB",
|
|
161
|
+
group: "SQL results",
|
|
162
|
+
min: KiB,
|
|
163
|
+
max: 64 * MiB,
|
|
164
|
+
step: MiB,
|
|
165
|
+
scale: MiB
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
key: "queryMs",
|
|
169
|
+
label: "Query timeout",
|
|
170
|
+
unit: "seconds",
|
|
171
|
+
group: "SQL results",
|
|
172
|
+
min: 1e3,
|
|
173
|
+
max: 3e5,
|
|
174
|
+
step: 1e3,
|
|
175
|
+
scale: 1e3
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
key: "requestsPerSecond",
|
|
179
|
+
label: "Request rate",
|
|
180
|
+
unit: "requests/s",
|
|
181
|
+
group: "Throughput",
|
|
182
|
+
min: 1,
|
|
183
|
+
max: 100,
|
|
184
|
+
step: 1
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
key: "bytesPerSecond",
|
|
188
|
+
label: "Data rate",
|
|
189
|
+
unit: "MiB/s",
|
|
190
|
+
group: "Throughput",
|
|
191
|
+
min: KiB,
|
|
192
|
+
max: 256 * MiB,
|
|
193
|
+
step: MiB,
|
|
194
|
+
scale: MiB
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
key: "liveConcurrency",
|
|
198
|
+
label: "Parallel streams",
|
|
199
|
+
unit: "streams",
|
|
200
|
+
group: "Throughput",
|
|
201
|
+
min: 1,
|
|
202
|
+
max: 64,
|
|
203
|
+
step: 1
|
|
204
|
+
}
|
|
205
|
+
];
|
|
206
|
+
function normalizePowerLogsLimits(input) {
|
|
207
|
+
const values = input !== null && typeof input === "object" ? input : {};
|
|
208
|
+
const normalized = { ...require_power_logs.POWER_LOGS_DEFAULT_LIMITS };
|
|
209
|
+
for (const field of LOG_LIMIT_FIELDS) {
|
|
210
|
+
const value = values[field.key];
|
|
211
|
+
if (typeof value === "number" && Number.isFinite(value)) normalized[field.key] = Math.max(field.min, Math.min(field.max, Math.trunc(value)));
|
|
212
|
+
}
|
|
213
|
+
normalized.batchBytes = Math.max(normalized.batchBytes, normalized.recordBytes + 3);
|
|
214
|
+
normalized.captureSourceBytes = Math.max(normalized.captureSourceBytes, normalized.recordBytes);
|
|
215
|
+
return normalized;
|
|
216
|
+
}
|
|
217
|
+
function applyPowerLogsLimits(input) {
|
|
218
|
+
const normalized = normalizePowerLogsLimits(input);
|
|
219
|
+
Object.assign(require_power_logs.POWER_LOGS_LIMITS, normalized);
|
|
220
|
+
return normalized;
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
exports.LOG_LIMIT_FIELDS = LOG_LIMIT_FIELDS;
|
|
224
|
+
exports.applyPowerLogsLimits = applyPowerLogsLimits;
|
|
225
|
+
exports.normalizePowerLogsLimits = normalizePowerLogsLimits;
|
|
226
|
+
|
|
227
|
+
//# sourceMappingURL=power-logs-limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-logs-limits.js","names":[],"sources":["../../../src/common/power-logs-limits.ts"],"sourcesContent":["import {\n POWER_LOGS_DEFAULT_LIMITS,\n POWER_LOGS_LIMITS,\n type PowerLogsLimitKey,\n type PowerLogsLimits,\n} from \"./power-logs\";\n\nexport interface LogLimitField {\n key: PowerLogsLimitKey;\n label: string;\n unit: string;\n group: \"Live logs\" | \"History\" | \"Captures\" | \"SQL results\" | \"Throughput\";\n min: number;\n max: number;\n step: number;\n scale?: number;\n}\n\nconst KiB = 1024;\nconst MiB = KiB * KiB;\n\nexport const LOG_LIMIT_FIELDS: readonly LogLimitField[] = [\n { key: \"liveRows\", label: \"Buffered rows\", unit: \"rows\", group: \"Live logs\", min: 1, max: 1000000, step: 1000 },\n {\n key: \"liveBytes\",\n label: \"Buffer size\",\n unit: \"MiB\",\n group: \"Live logs\",\n min: KiB,\n max: 1024 * MiB,\n step: MiB,\n scale: MiB,\n },\n { key: \"batchRows\", label: \"Batch rows\", unit: \"rows\", group: \"Live logs\", min: 1, max: 100000, step: 100 },\n {\n key: \"batchBytes\",\n label: \"Batch size\",\n unit: \"MiB\",\n group: \"Live logs\",\n min: KiB,\n max: 64 * MiB,\n step: MiB,\n scale: MiB,\n },\n {\n key: \"recordBytes\",\n label: \"Record size\",\n unit: \"KiB\",\n group: \"Live logs\",\n min: KiB,\n max: 16 * MiB,\n step: KiB,\n scale: KiB,\n },\n { key: \"historyLines\", label: \"Lines per source\", unit: \"lines\", group: \"History\", min: 1, max: 1000000, step: 1000 },\n {\n key: \"historyBytes\",\n label: \"Bytes per source\",\n unit: \"MiB\",\n group: \"History\",\n min: KiB,\n max: 256 * MiB,\n step: MiB,\n scale: MiB,\n },\n {\n key: \"historyConcurrency\",\n label: \"Parallel requests\",\n unit: \"requests\",\n group: \"History\",\n min: 1,\n max: 32,\n step: 1,\n },\n {\n key: \"captureBytes\",\n label: \"Capture size\",\n unit: \"MiB\",\n group: \"Captures\",\n min: KiB,\n max: 4096 * MiB,\n step: MiB,\n scale: MiB,\n },\n {\n key: \"captureRows\",\n label: \"Rows per capture\",\n unit: \"rows\",\n group: \"Captures\",\n min: 1,\n max: 10000000,\n step: 10000,\n },\n { key: \"captures\", label: \"Retained captures\", unit: \"captures\", group: \"Captures\", min: 1, max: 100, step: 1 },\n { key: \"sources\", label: \"Sources per capture\", unit: \"sources\", group: \"Captures\", min: 1, max: 2000, step: 10 },\n {\n key: \"captureSourceLines\",\n label: \"Lines per source\",\n unit: \"lines\",\n group: \"Captures\",\n min: 1,\n max: 1000000,\n step: 1000,\n },\n {\n key: \"captureSourceBytes\",\n label: \"Bytes per source\",\n unit: \"MiB\",\n group: \"Captures\",\n min: KiB,\n max: 256 * MiB,\n step: MiB,\n scale: MiB,\n },\n {\n key: \"ttlMs\",\n label: \"Retention\",\n unit: \"minutes\",\n group: \"Captures\",\n min: 60000,\n max: 7 * 24 * 60 * 60000,\n step: 60000,\n scale: 60000,\n },\n { key: \"resultRows\", label: \"Result rows\", unit: \"rows\", group: \"SQL results\", min: 1, max: 100000, step: 100 },\n {\n key: \"resultBytes\",\n label: \"Result size\",\n unit: \"MiB\",\n group: \"SQL results\",\n min: KiB,\n max: 64 * MiB,\n step: MiB,\n scale: MiB,\n },\n {\n key: \"queryMs\",\n label: \"Query timeout\",\n unit: \"seconds\",\n group: \"SQL results\",\n min: 1000,\n max: 300000,\n step: 1000,\n scale: 1000,\n },\n {\n key: \"requestsPerSecond\",\n label: \"Request rate\",\n unit: \"requests/s\",\n group: \"Throughput\",\n min: 1,\n max: 100,\n step: 1,\n },\n {\n key: \"bytesPerSecond\",\n label: \"Data rate\",\n unit: \"MiB/s\",\n group: \"Throughput\",\n min: KiB,\n max: 256 * MiB,\n step: MiB,\n scale: MiB,\n },\n { key: \"liveConcurrency\", label: \"Parallel streams\", unit: \"streams\", group: \"Throughput\", min: 1, max: 64, step: 1 },\n];\n\nexport function normalizePowerLogsLimits(input: unknown): PowerLogsLimits {\n const values = input !== null && typeof input === \"object\" ? (input as Record<string, unknown>) : {};\n const normalized: PowerLogsLimits = { ...POWER_LOGS_DEFAULT_LIMITS };\n for (const field of LOG_LIMIT_FIELDS) {\n const value = values[field.key];\n if (typeof value === \"number\" && Number.isFinite(value)) {\n normalized[field.key] = Math.max(field.min, Math.min(field.max, Math.trunc(value)));\n }\n }\n normalized.batchBytes = Math.max(normalized.batchBytes, normalized.recordBytes + 3);\n normalized.captureSourceBytes = Math.max(normalized.captureSourceBytes, normalized.recordBytes);\n return normalized;\n}\n\nexport function applyPowerLogsLimits(input: unknown): PowerLogsLimits {\n const normalized = normalizePowerLogsLimits(input);\n Object.assign(POWER_LOGS_LIMITS, normalized);\n return normalized;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/common/power-logs.ts
|
|
2
|
+
var POWER_LOGS_CHANNEL = "freelens-power:logs";
|
|
3
|
+
var POWER_LOGS_DEFAULT_LIMITS = {
|
|
4
|
+
liveRows: 1e4,
|
|
5
|
+
liveBytes: 16 * 1024 * 1024,
|
|
6
|
+
batchRows: 1e3,
|
|
7
|
+
batchBytes: 2 * 1024 * 1024,
|
|
8
|
+
recordBytes: 64 * 1024,
|
|
9
|
+
captureBytes: 256 * 1024 * 1024,
|
|
10
|
+
captureRows: 1e6,
|
|
11
|
+
captures: 3,
|
|
12
|
+
sources: 200,
|
|
13
|
+
resultRows: 1e3,
|
|
14
|
+
resultBytes: 2 * 1024 * 1024,
|
|
15
|
+
queryMs: 15e3,
|
|
16
|
+
ttlMs: 3600 * 1e3,
|
|
17
|
+
historyLines: 1e3,
|
|
18
|
+
historyBytes: 1024 * 1024,
|
|
19
|
+
captureSourceLines: 1e4,
|
|
20
|
+
captureSourceBytes: 8 * 1024 * 1024,
|
|
21
|
+
requestsPerSecond: 2,
|
|
22
|
+
bytesPerSecond: 1024 * 1024,
|
|
23
|
+
historyConcurrency: 2,
|
|
24
|
+
liveConcurrency: 4
|
|
25
|
+
};
|
|
26
|
+
var POWER_LOGS_LIMITS = { ...POWER_LOGS_DEFAULT_LIMITS };
|
|
27
|
+
//#endregion
|
|
28
|
+
exports.POWER_LOGS_CHANNEL = POWER_LOGS_CHANNEL;
|
|
29
|
+
exports.POWER_LOGS_DEFAULT_LIMITS = POWER_LOGS_DEFAULT_LIMITS;
|
|
30
|
+
exports.POWER_LOGS_LIMITS = POWER_LOGS_LIMITS;
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=power-logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-logs.js","names":[],"sources":["../../../src/common/power-logs.ts"],"sourcesContent":["export const POWER_LOGS_CHANNEL = \"freelens-power:logs\";\nexport const POWER_LOGS_DEFAULT_LIMITS = {\n liveRows: 10000,\n liveBytes: 16 * 1024 * 1024,\n batchRows: 1000,\n batchBytes: 2 * 1024 * 1024,\n recordBytes: 64 * 1024,\n captureBytes: 256 * 1024 * 1024,\n captureRows: 1000000,\n captures: 3,\n sources: 200,\n resultRows: 1000,\n resultBytes: 2 * 1024 * 1024,\n queryMs: 15000,\n ttlMs: 60 * 60 * 1000,\n historyLines: 1000,\n historyBytes: 1024 * 1024,\n captureSourceLines: 10000,\n captureSourceBytes: 8 * 1024 * 1024,\n requestsPerSecond: 2,\n bytesPerSecond: 1024 * 1024,\n historyConcurrency: 2,\n liveConcurrency: 4,\n} as const;\n\nexport type PowerLogsLimitKey = keyof typeof POWER_LOGS_DEFAULT_LIMITS;\nexport type PowerLogsLimits = { [Key in PowerLogsLimitKey]: number };\nexport const POWER_LOGS_LIMITS: PowerLogsLimits = { ...POWER_LOGS_DEFAULT_LIMITS };\n\nexport type LogLevel = \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\" | \"unknown\";\nexport type LogWorkloadKind = \"Pod\" | \"Deployment\" | \"DaemonSet\" | \"StatefulSet\" | \"ReplicaSet\" | \"Job\" | \"CronJob\";\nexport interface LogTarget {\n kind: LogWorkloadKind;\n namespace: string;\n name: string;\n uid: string;\n}\nexport interface LogSource {\n namespace: string;\n pod: string;\n podUid: string;\n container: string;\n previous?: boolean;\n}\nexport interface LogRecord {\n timestamp: number | null;\n pod: string;\n podUid: string;\n container: string;\n level: LogLevel;\n message: string;\n fieldsJson: string | null;\n previous?: boolean;\n}\nexport interface LogCapture {\n id: string;\n target: LogTarget;\n createdAt: number;\n expiresAt: number;\n state: \"collecting\" | \"ready\" | \"partial\";\n rows: number;\n bytes: number;\n notes: string[];\n}\nexport type LogCell = string | number | boolean | null;\nexport interface LogQueryResult {\n error?: string;\n columns: string[];\n rows: LogCell[][];\n truncated: boolean;\n elapsedMs: number;\n}\nexport interface LogPartition {\n clusterId: string;\n contextId: string;\n}\nexport type LogRequest = LogPartition &\n (\n | { operation: \"permit\"; lane: \"start\" | \"bytes\"; bytes?: number }\n | { operation: \"stream-open\"; streamId: string; follow: boolean }\n | { operation: \"stream-close\" | \"stream-renew\"; streamId: string }\n | { operation: \"create\"; target: LogTarget }\n | { operation: \"append\"; captureId: string; records: LogRecord[] }\n | { operation: \"finish\"; captureId: string; partial: boolean; notes: string[] }\n | { operation: \"list\" }\n | { operation: \"delete\"; captureId: string }\n | { operation: \"query\"; captureId: string; queryId: string; sql: string }\n | { operation: \"cancel\"; queryId: string }\n | { operation: \"export\"; captureId: string }\n );\n"],"mappings":";AAAA,IAAa,qBAAqB;AAClC,IAAa,4BAA4B;CACvC,UAAU;CACV,WAAW,KAAK,OAAO;CACvB,WAAW;CACX,YAAY,IAAI,OAAO;CACvB,aAAa,KAAK;CAClB,cAAc,MAAM,OAAO;CAC3B,aAAa;CACb,UAAU;CACV,SAAS;CACT,YAAY;CACZ,aAAa,IAAI,OAAO;CACxB,SAAS;CACT,OAAO,OAAU;CACjB,cAAc;CACd,cAAc,OAAO;CACrB,oBAAoB;CACpB,oBAAoB,IAAI,OAAO;CAC/B,mBAAmB;CACnB,gBAAgB,OAAO;CACvB,oBAAoB;CACpB,iBAAiB;AACnB;AAIA,IAAa,oBAAqC,EAAE,GAAG,0BAA0B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//#region src/common/resource-search.ts
|
|
2
|
+
var RESOURCE_SEARCH_CHANNEL = "freelens-power:resource-search";
|
|
3
|
+
var identifier = (value, maximum = 253) => typeof value === "string" && value.length > 0 && value.length <= maximum && /^[a-zA-Z0-9_.:-]+$/.test(value);
|
|
4
|
+
var objectName = (value) => typeof value === "string" && value.length > 0 && value.length <= 1024 && value !== "." && value !== ".." && !/[/%\x00-\x1f\x7f]/.test(value);
|
|
5
|
+
function validSearchPartition(value) {
|
|
6
|
+
const request = value;
|
|
7
|
+
return !!request && identifier(request.clusterId, 128) && identifier(request.contextId, 256);
|
|
8
|
+
}
|
|
9
|
+
function projectSearchDocuments(input) {
|
|
10
|
+
if (!Array.isArray(input) || input.length > 500) throw new Error("Invalid search batch");
|
|
11
|
+
return input.map((document) => {
|
|
12
|
+
if (!document || !identifier(document.kind) || !objectName(document.name) || !identifier(document.version) || !identifier(document.resource) || !(document.group === "" || identifier(document.group)) || !(document.namespace === void 0 || identifier(document.namespace)) || !(document.uid === void 0 || identifier(document.uid, 128))) throw new Error("Invalid search identity");
|
|
13
|
+
const path = `${document.group ? `/apis/${encodeURIComponent(document.group)}` : "/api"}/${encodeURIComponent(document.version)}/${document.namespace ? `namespaces/${encodeURIComponent(document.namespace)}/` : ""}${encodeURIComponent(document.resource)}/${encodeURIComponent(document.name)}`;
|
|
14
|
+
if (document.path !== path) throw new Error("Invalid search path");
|
|
15
|
+
const labels = Object.fromEntries(Object.entries(document.labels ?? {}).slice(0, 64).filter(([key, value]) => key.length <= 253 && typeof value === "string" && value.length <= 256));
|
|
16
|
+
const fields = (/* @__PURE__ */ new Set([
|
|
17
|
+
"/pods",
|
|
18
|
+
"/nodes",
|
|
19
|
+
"/services",
|
|
20
|
+
"/namespaces",
|
|
21
|
+
"apps/deployments",
|
|
22
|
+
"apps/statefulsets",
|
|
23
|
+
"apps/daemonsets",
|
|
24
|
+
"apps/replicasets",
|
|
25
|
+
"batch/jobs",
|
|
26
|
+
"batch/cronjobs",
|
|
27
|
+
"networking.k8s.io/ingresses",
|
|
28
|
+
"autoscaling/horizontalpodautoscalers"
|
|
29
|
+
])).has(`${document.group}/${document.resource}`) ? (document.fields ?? []).slice(0, 32).flatMap((field) => field && typeof field.label === "string" && typeof field.text === "string" ? [{
|
|
30
|
+
label: field.label.slice(0, 64),
|
|
31
|
+
text: field.text.slice(0, 512)
|
|
32
|
+
}] : []) : [];
|
|
33
|
+
let remaining = 4096;
|
|
34
|
+
return {
|
|
35
|
+
kind: document.kind,
|
|
36
|
+
name: document.name,
|
|
37
|
+
namespace: document.namespace,
|
|
38
|
+
labels,
|
|
39
|
+
path,
|
|
40
|
+
group: document.group,
|
|
41
|
+
version: document.version,
|
|
42
|
+
resource: document.resource,
|
|
43
|
+
uid: document.uid,
|
|
44
|
+
aliases: Array.isArray(document.aliases) ? document.aliases.filter((alias) => typeof alias === "string" && /^[a-zA-Z0-9_.:-]{1,128}$/.test(alias)).slice(0, 32) : [],
|
|
45
|
+
fields: fields.flatMap((field) => {
|
|
46
|
+
const text = field.text.slice(0, Math.max(0, remaining));
|
|
47
|
+
remaining -= text.length;
|
|
48
|
+
return text ? [{
|
|
49
|
+
label: field.label,
|
|
50
|
+
text
|
|
51
|
+
}] : [];
|
|
52
|
+
})
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
exports.RESOURCE_SEARCH_CHANNEL = RESOURCE_SEARCH_CHANNEL;
|
|
58
|
+
exports.projectSearchDocuments = projectSearchDocuments;
|
|
59
|
+
exports.validSearchPartition = validSearchPartition;
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=resource-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-search.js","names":[],"sources":["../../../src/common/resource-search.ts"],"sourcesContent":["export const RESOURCE_SEARCH_CHANNEL = \"freelens-power:resource-search\";\nexport interface SearchDocument {\n kind: string;\n name: string;\n namespace?: string;\n labels: Record<string, string>;\n path: string;\n group: string;\n version: string;\n resource: string;\n uid?: string;\n aliases?: string[];\n fields?: { label: string; text: string }[];\n}\nexport interface SearchQueryResult {\n documents: SearchDocument[];\n total: number;\n hasMore: boolean;\n}\nexport interface SearchIndexStatus {\n count: number;\n bytes: number;\n available: boolean;\n}\nexport type SearchIndexRequest = { clusterId: string; contextId: string } & (\n | { operation: \"begin\"; scope: string; scanId: string }\n | { operation: \"complete\"; scope: string; scanId: string }\n | { operation: \"append\"; scope: string; scanId: string; documents: SearchDocument[] }\n | { operation: \"invalidate\"; scope: string }\n | { operation: \"reconcile\"; resources: string[] }\n | { operation: \"permit\" }\n | { operation: \"query\"; query: string; limit?: number; kind?: string; namespace?: string }\n | { operation: \"status\" }\n | { operation: \"clear\" }\n);\n\nconst identifier = (value: unknown, maximum = 253): value is string =>\n typeof value === \"string\" && value.length > 0 && value.length <= maximum && /^[a-zA-Z0-9_.:-]+$/.test(value);\nconst objectName = (value: unknown): value is string =>\n typeof value === \"string\" &&\n value.length > 0 &&\n value.length <= 1024 &&\n value !== \".\" &&\n value !== \"..\" &&\n !/[/%\\x00-\\x1f\\x7f]/.test(value);\n\nexport function validSearchPartition(value: unknown): value is { clusterId: string; contextId: string } {\n const request = value as SearchIndexRequest;\n return !!request && identifier(request.clusterId, 128) && identifier(request.contextId, 256);\n}\n\nexport function projectSearchDocuments(input: unknown): SearchDocument[] {\n if (!Array.isArray(input) || input.length > 500) throw new Error(\"Invalid search batch\");\n return input.map((document: SearchDocument) => {\n if (\n !document ||\n !identifier(document.kind) ||\n !objectName(document.name) ||\n !identifier(document.version) ||\n !identifier(document.resource) ||\n !(document.group === \"\" || identifier(document.group)) ||\n !(document.namespace === undefined || identifier(document.namespace)) ||\n !(document.uid === undefined || identifier(document.uid, 128))\n )\n throw new Error(\"Invalid search identity\");\n const path = `${document.group ? `/apis/${encodeURIComponent(document.group)}` : \"/api\"}/${encodeURIComponent(document.version)}/${document.namespace ? `namespaces/${encodeURIComponent(document.namespace)}/` : \"\"}${encodeURIComponent(document.resource)}/${encodeURIComponent(document.name)}`;\n if (document.path !== path) throw new Error(\"Invalid search path\");\n const labels = Object.fromEntries(\n Object.entries(document.labels ?? {})\n .slice(0, 64)\n .filter(([key, value]) => key.length <= 253 && typeof value === \"string\" && value.length <= 256),\n );\n const reviewedCollections = new Set([\n \"/pods\",\n \"/nodes\",\n \"/services\",\n \"/namespaces\",\n \"apps/deployments\",\n \"apps/statefulsets\",\n \"apps/daemonsets\",\n \"apps/replicasets\",\n \"batch/jobs\",\n \"batch/cronjobs\",\n \"networking.k8s.io/ingresses\",\n \"autoscaling/horizontalpodautoscalers\",\n ]);\n const fields = reviewedCollections.has(`${document.group}/${document.resource}`)\n ? (document.fields ?? [])\n .slice(0, 32)\n .flatMap((field) =>\n field && typeof field.label === \"string\" && typeof field.text === \"string\"\n ? [{ label: field.label.slice(0, 64), text: field.text.slice(0, 512) }]\n : [],\n )\n : [];\n let remaining = 4096;\n return {\n kind: document.kind,\n name: document.name,\n namespace: document.namespace,\n labels,\n path,\n group: document.group,\n version: document.version,\n resource: document.resource,\n uid: document.uid,\n aliases: Array.isArray(document.aliases)\n ? document.aliases\n .filter((alias) => typeof alias === \"string\" && /^[a-zA-Z0-9_.:-]{1,128}$/.test(alias))\n .slice(0, 32)\n : [],\n fields: fields.flatMap((field) => {\n const text = field.text.slice(0, Math.max(0, remaining));\n remaining -= text.length;\n return text ? [{ label: field.label, text }] : [];\n }),\n };\n });\n}\n"],"mappings":";AAAA,IAAa,0BAA0B;AAoCvC,IAAM,cAAc,OAAgB,UAAU,QAC5C,OAAO,UAAU,YAAY,MAAM,SAAS,KAAK,MAAM,UAAU,WAAW,qBAAqB,KAAK,KAAK;AAC7G,IAAM,cAAc,UAClB,OAAO,UAAU,YACjB,MAAM,SAAS,KACf,MAAM,UAAU,QAChB,UAAU,OACV,UAAU,QACV,CAAC,oBAAoB,KAAK,KAAK;AAEjC,SAAgB,qBAAqB,OAAmE;CACtG,MAAM,UAAU;CAChB,OAAO,CAAC,CAAC,WAAW,WAAW,QAAQ,WAAW,GAAG,KAAK,WAAW,QAAQ,WAAW,GAAG;AAC7F;AAEA,SAAgB,uBAAuB,OAAkC;CACvE,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,KAAK,MAAM,IAAI,MAAM,sBAAsB;CACvF,OAAO,MAAM,KAAK,aAA6B;EAC7C,IACE,CAAC,YACD,CAAC,WAAW,SAAS,IAAI,KACzB,CAAC,WAAW,SAAS,IAAI,KACzB,CAAC,WAAW,SAAS,OAAO,KAC5B,CAAC,WAAW,SAAS,QAAQ,KAC7B,EAAE,SAAS,UAAU,MAAM,WAAW,SAAS,KAAK,MACpD,EAAE,SAAS,cAAc,KAAA,KAAa,WAAW,SAAS,SAAS,MACnE,EAAE,SAAS,QAAQ,KAAA,KAAa,WAAW,SAAS,KAAK,GAAG,IAE5D,MAAM,IAAI,MAAM,yBAAyB;EAC3C,MAAM,OAAO,GAAG,SAAS,QAAQ,SAAS,mBAAmB,SAAS,KAAK,MAAM,OAAO,GAAG,mBAAmB,SAAS,OAAO,EAAE,GAAG,SAAS,YAAY,cAAc,mBAAmB,SAAS,SAAS,EAAE,KAAK,KAAK,mBAAmB,SAAS,QAAQ,EAAE,GAAG,mBAAmB,SAAS,IAAI;EAChS,IAAI,SAAS,SAAS,MAAM,MAAM,IAAI,MAAM,qBAAqB;EACjE,MAAM,SAAS,OAAO,YACpB,OAAO,QAAQ,SAAS,UAAU,CAAC,CAAC,CAAC,CAClC,MAAM,GAAG,EAAE,CAAC,CACZ,QAAQ,CAAC,KAAK,WAAW,IAAI,UAAU,OAAO,OAAO,UAAU,YAAY,MAAM,UAAU,GAAG,CACnG;EAeA,MAAM,0BAAS,IAdiB,IAAI;GAClC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CACe,EAAA,CAAoB,IAAI,GAAG,SAAS,MAAM,GAAG,SAAS,UAAU,KAC1E,SAAS,UAAU,CAAC,EAAA,CAClB,MAAM,GAAG,EAAE,CAAC,CACZ,SAAS,UACR,SAAS,OAAO,MAAM,UAAU,YAAY,OAAO,MAAM,SAAS,WAC9D,CAAC;GAAE,OAAO,MAAM,MAAM,MAAM,GAAG,EAAE;GAAG,MAAM,MAAM,KAAK,MAAM,GAAG,GAAG;EAAE,CAAC,IACpE,CAAC,CACP,IACF,CAAC;EACL,IAAI,YAAY;EAChB,OAAO;GACL,MAAM,SAAS;GACf,MAAM,SAAS;GACf,WAAW,SAAS;GACpB;GACA;GACA,OAAO,SAAS;GAChB,SAAS,SAAS;GAClB,UAAU,SAAS;GACnB,KAAK,SAAS;GACd,SAAS,MAAM,QAAQ,SAAS,OAAO,IACnC,SAAS,QACN,QAAQ,UAAU,OAAO,UAAU,YAAY,2BAA2B,KAAK,KAAK,CAAC,CAAC,CACtF,MAAM,GAAG,EAAE,IACd,CAAC;GACL,QAAQ,OAAO,SAAS,UAAU;IAChC,MAAM,OAAO,MAAM,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,SAAS,CAAC;IACvD,aAAa,KAAK;IAClB,OAAO,OAAO,CAAC;KAAE,OAAO,MAAM;KAAO;IAAK,CAAC,IAAI,CAAC;GAClD,CAAC;EACH;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const require_extensions = require("../../_virtual/_global-external_@freelensapp/extensions.js");
|
|
2
|
+
const require__global_external_mobx = require("../../_virtual/_global-external_mobx.js");
|
|
3
|
+
const require_power_logs_limits = require("../power-logs-limits.js");
|
|
4
|
+
//#region src/common/store/logs-preferences-store.ts
|
|
5
|
+
var LogsPreferencesStore = class extends require_extensions.Common.Store.ExtensionStore {
|
|
6
|
+
enabled = false;
|
|
7
|
+
gentle = true;
|
|
8
|
+
compactRows = false;
|
|
9
|
+
limits = require_power_logs_limits.normalizePowerLogsLimits(void 0);
|
|
10
|
+
constructor() {
|
|
11
|
+
super({
|
|
12
|
+
configName: "logs-preferences",
|
|
13
|
+
defaults: {
|
|
14
|
+
enabled: false,
|
|
15
|
+
gentle: true,
|
|
16
|
+
compactRows: false,
|
|
17
|
+
limits: require_power_logs_limits.normalizePowerLogsLimits(void 0)
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
require__global_external_mobx.makeObservable(this, {
|
|
21
|
+
enabled: require__global_external_mobx.observable,
|
|
22
|
+
gentle: require__global_external_mobx.observable,
|
|
23
|
+
compactRows: require__global_external_mobx.observable,
|
|
24
|
+
limits: require__global_external_mobx.observable
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
fromStore(data) {
|
|
28
|
+
this.enabled = data?.enabled === true;
|
|
29
|
+
this.gentle = data?.gentle !== false;
|
|
30
|
+
this.compactRows = data?.compactRows === true;
|
|
31
|
+
this.limits = require_power_logs_limits.normalizePowerLogsLimits(data?.limits);
|
|
32
|
+
}
|
|
33
|
+
toJSON() {
|
|
34
|
+
return {
|
|
35
|
+
enabled: this.enabled,
|
|
36
|
+
gentle: this.gentle,
|
|
37
|
+
compactRows: this.compactRows,
|
|
38
|
+
limits: require_power_logs_limits.normalizePowerLogsLimits(this.limits)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
exports.LogsPreferencesStore = LogsPreferencesStore;
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=logs-preferences-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs-preferences-store.js","names":[],"sources":["../../../../src/common/store/logs-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { makeObservable, observable } from \"mobx\";\nimport { normalizePowerLogsLimits } from \"../power-logs-limits\";\n\nimport type { PowerLogsLimits } from \"../power-logs\";\n\nexport class LogsPreferencesStore extends Common.Store.ExtensionStore<{\n enabled: boolean;\n gentle: boolean;\n compactRows: boolean;\n limits: PowerLogsLimits;\n}> {\n enabled = false;\n gentle = true;\n compactRows = false;\n limits = normalizePowerLogsLimits(undefined);\n\n constructor() {\n super({\n configName: \"logs-preferences\",\n defaults: { enabled: false, gentle: true, compactRows: false, limits: normalizePowerLogsLimits(undefined) },\n });\n makeObservable(this, { enabled: observable, gentle: observable, compactRows: observable, limits: observable });\n }\n\n fromStore(data: { enabled?: boolean; gentle?: boolean; compactRows?: boolean; limits?: unknown }): void {\n this.enabled = data?.enabled === true;\n this.gentle = data?.gentle !== false;\n this.compactRows = data?.compactRows === true;\n this.limits = normalizePowerLogsLimits(data?.limits);\n }\n\n toJSON() {\n return {\n enabled: this.enabled,\n gentle: this.gentle,\n compactRows: this.compactRows,\n limits: normalizePowerLogsLimits(this.limits),\n };\n }\n}\n"],"mappings":";;;;AAMA,IAAa,uBAAb,cAA0C,mBAAA,OAAO,MAAM,eAKpD;CACD,UAAU;CACV,SAAS;CACT,cAAc;CACd,SAAS,0BAAA,yBAAyB,KAAA,CAAS;CAE3C,cAAc;EACZ,MAAM;GACJ,YAAY;GACZ,UAAU;IAAE,SAAS;IAAO,QAAQ;IAAM,aAAa;IAAO,QAAQ,0BAAA,yBAAyB,KAAA,CAAS;GAAE;EAC5G,CAAC;EACD,8BAAA,eAAe,MAAM;GAAE,SAAS,8BAAA;GAAY,QAAQ,8BAAA;GAAY,aAAa,8BAAA;GAAY,QAAQ,8BAAA;EAAW,CAAC;CAC/G;CAEA,UAAU,MAA8F;EACtG,KAAK,UAAU,MAAM,YAAY;EACjC,KAAK,SAAS,MAAM,WAAW;EAC/B,KAAK,cAAc,MAAM,gBAAgB;EACzC,KAAK,SAAS,0BAAA,yBAAyB,MAAM,MAAM;CACrD;CAEA,SAAS;EACP,OAAO;GACL,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,aAAa,KAAK;GAClB,QAAQ,0BAAA,yBAAyB,KAAK,MAAM;EAC9C;CACF;AACF"}
|
|
@@ -6,6 +6,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
6
6
|
enabled = false;
|
|
7
7
|
diagnosticsVisible = true;
|
|
8
8
|
relationshipsVisible = true;
|
|
9
|
+
resourceSearchEnabled = true;
|
|
9
10
|
hiddenUpstreamClusters = [];
|
|
10
11
|
historyEnabled = false;
|
|
11
12
|
trackedHistory = [];
|
|
@@ -16,6 +17,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
16
17
|
enabled: false,
|
|
17
18
|
diagnosticsVisible: true,
|
|
18
19
|
relationshipsVisible: true,
|
|
20
|
+
resourceSearchEnabled: true,
|
|
19
21
|
hiddenUpstreamClusters: [],
|
|
20
22
|
historyEnabled: false,
|
|
21
23
|
trackedHistory: []
|
|
@@ -25,6 +27,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
25
27
|
enabled: require__global_external_mobx.observable,
|
|
26
28
|
diagnosticsVisible: require__global_external_mobx.observable,
|
|
27
29
|
relationshipsVisible: require__global_external_mobx.observable,
|
|
30
|
+
resourceSearchEnabled: require__global_external_mobx.observable,
|
|
28
31
|
hiddenUpstreamClusters: require__global_external_mobx.observable,
|
|
29
32
|
historyEnabled: require__global_external_mobx.observable,
|
|
30
33
|
trackedHistory: require__global_external_mobx.observable,
|
|
@@ -35,6 +38,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
35
38
|
this.enabled = data?.enabled === true;
|
|
36
39
|
this.diagnosticsVisible = data?.diagnosticsVisible !== false;
|
|
37
40
|
this.relationshipsVisible = data?.relationshipsVisible !== false;
|
|
41
|
+
this.resourceSearchEnabled = data?.resourceSearchEnabled !== false;
|
|
38
42
|
this.hiddenUpstreamClusters = Array.isArray(data?.hiddenUpstreamClusters) ? [...new Set(data.hiddenUpstreamClusters.filter((id) => typeof id === "string" && id.length > 0 && id.length <= 256))].slice(-100) : [];
|
|
39
43
|
this.historyEnabled = data?.historyEnabled === true;
|
|
40
44
|
this.trackedHistory = Array.isArray(data?.trackedHistory) ? data.trackedHistory.filter(require_monitoring_history.validHistoryIdentity).slice(0, 100).map(({ clusterId, scope, uid }) => ({
|
|
@@ -48,6 +52,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
48
52
|
enabled: this.enabled,
|
|
49
53
|
diagnosticsVisible: this.diagnosticsVisible,
|
|
50
54
|
relationshipsVisible: this.relationshipsVisible,
|
|
55
|
+
resourceSearchEnabled: this.resourceSearchEnabled,
|
|
51
56
|
hiddenUpstreamClusters: [...this.hiddenUpstreamClusters],
|
|
52
57
|
historyEnabled: this.historyEnabled,
|
|
53
58
|
trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitoring-preferences-store.js","names":[],"sources":["../../../../src/common/store/monitoring-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\nimport { type HistoryIdentity, validHistoryIdentity } from \"../monitoring-history\";\n\nexport class MonitoringPreferencesStore extends Common.Store.ExtensionStore<{\n enabled: boolean;\n diagnosticsVisible: boolean;\n relationshipsVisible: boolean;\n hiddenUpstreamClusters: string[];\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n}> {\n enabled = false;\n diagnosticsVisible = true;\n relationshipsVisible = true;\n hiddenUpstreamClusters: string[] = [];\n historyEnabled = false;\n trackedHistory: HistoryIdentity[] = [];\n\n constructor() {\n super({\n configName: \"monitoring-preferences\",\n defaults: {\n enabled: false,\n diagnosticsVisible: true,\n relationshipsVisible: true,\n hiddenUpstreamClusters: [],\n historyEnabled: false,\n trackedHistory: [],\n },\n });\n makeObservable(this, {\n enabled: observable,\n diagnosticsVisible: observable,\n relationshipsVisible: observable,\n hiddenUpstreamClusters: observable,\n historyEnabled: observable,\n trackedHistory: observable,\n fromStore: action,\n });\n }\n\n fromStore(data: {\n enabled?: boolean;\n diagnosticsVisible?: boolean;\n relationshipsVisible?: boolean;\n hiddenUpstreamClusters?: string[];\n historyEnabled?: boolean;\n trackedHistory?: HistoryIdentity[];\n }): void {\n this.enabled = data?.enabled === true;\n this.diagnosticsVisible = data?.diagnosticsVisible !== false;\n this.relationshipsVisible = data?.relationshipsVisible !== false;\n this.hiddenUpstreamClusters = Array.isArray(data?.hiddenUpstreamClusters)\n ? [\n ...new Set(\n data.hiddenUpstreamClusters.filter((id) => typeof id === \"string\" && id.length > 0 && id.length <= 256),\n ),\n ].slice(-100)\n : [];\n this.historyEnabled = data?.historyEnabled === true;\n this.trackedHistory = Array.isArray(data?.trackedHistory)\n ? data.trackedHistory\n .filter(validHistoryIdentity)\n .slice(0, 100)\n .map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid }))\n : [];\n }\n\n toJSON(): {\n enabled: boolean;\n diagnosticsVisible: boolean;\n relationshipsVisible: boolean;\n hiddenUpstreamClusters: string[];\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n } {\n return {\n enabled: this.enabled,\n diagnosticsVisible: this.diagnosticsVisible,\n relationshipsVisible: this.relationshipsVisible,\n hiddenUpstreamClusters: [...this.hiddenUpstreamClusters],\n historyEnabled: this.historyEnabled,\n trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid })),\n };\n }\n}\n"],"mappings":";;;;AAIA,IAAa,6BAAb,cAAgD,mBAAA,OAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"monitoring-preferences-store.js","names":[],"sources":["../../../../src/common/store/monitoring-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\nimport { type HistoryIdentity, validHistoryIdentity } from \"../monitoring-history\";\n\nexport class MonitoringPreferencesStore extends Common.Store.ExtensionStore<{\n enabled: boolean;\n diagnosticsVisible: boolean;\n relationshipsVisible: boolean;\n resourceSearchEnabled: boolean;\n hiddenUpstreamClusters: string[];\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n}> {\n enabled = false;\n diagnosticsVisible = true;\n relationshipsVisible = true;\n resourceSearchEnabled = true;\n hiddenUpstreamClusters: string[] = [];\n historyEnabled = false;\n trackedHistory: HistoryIdentity[] = [];\n\n constructor() {\n super({\n configName: \"monitoring-preferences\",\n defaults: {\n enabled: false,\n diagnosticsVisible: true,\n relationshipsVisible: true,\n resourceSearchEnabled: true,\n hiddenUpstreamClusters: [],\n historyEnabled: false,\n trackedHistory: [],\n },\n });\n makeObservable(this, {\n enabled: observable,\n diagnosticsVisible: observable,\n relationshipsVisible: observable,\n resourceSearchEnabled: observable,\n hiddenUpstreamClusters: observable,\n historyEnabled: observable,\n trackedHistory: observable,\n fromStore: action,\n });\n }\n\n fromStore(data: {\n enabled?: boolean;\n diagnosticsVisible?: boolean;\n relationshipsVisible?: boolean;\n resourceSearchEnabled?: boolean;\n hiddenUpstreamClusters?: string[];\n historyEnabled?: boolean;\n trackedHistory?: HistoryIdentity[];\n }): void {\n this.enabled = data?.enabled === true;\n this.diagnosticsVisible = data?.diagnosticsVisible !== false;\n this.relationshipsVisible = data?.relationshipsVisible !== false;\n this.resourceSearchEnabled = data?.resourceSearchEnabled !== false;\n this.hiddenUpstreamClusters = Array.isArray(data?.hiddenUpstreamClusters)\n ? [\n ...new Set(\n data.hiddenUpstreamClusters.filter((id) => typeof id === \"string\" && id.length > 0 && id.length <= 256),\n ),\n ].slice(-100)\n : [];\n this.historyEnabled = data?.historyEnabled === true;\n this.trackedHistory = Array.isArray(data?.trackedHistory)\n ? data.trackedHistory\n .filter(validHistoryIdentity)\n .slice(0, 100)\n .map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid }))\n : [];\n }\n\n toJSON(): {\n enabled: boolean;\n diagnosticsVisible: boolean;\n relationshipsVisible: boolean;\n resourceSearchEnabled: boolean;\n hiddenUpstreamClusters: string[];\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n } {\n return {\n enabled: this.enabled,\n diagnosticsVisible: this.diagnosticsVisible,\n relationshipsVisible: this.relationshipsVisible,\n resourceSearchEnabled: this.resourceSearchEnabled,\n hiddenUpstreamClusters: [...this.hiddenUpstreamClusters],\n historyEnabled: this.historyEnabled,\n trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid })),\n };\n }\n}\n"],"mappings":";;;;AAIA,IAAa,6BAAb,cAAgD,mBAAA,OAAO,MAAM,eAQ1D;CACD,UAAU;CACV,qBAAqB;CACrB,uBAAuB;CACvB,wBAAwB;CACxB,yBAAmC,CAAC;CACpC,iBAAiB;CACjB,iBAAoC,CAAC;CAErC,cAAc;EACZ,MAAM;GACJ,YAAY;GACZ,UAAU;IACR,SAAS;IACT,oBAAoB;IACpB,sBAAsB;IACtB,uBAAuB;IACvB,wBAAwB,CAAC;IACzB,gBAAgB;IAChB,gBAAgB,CAAC;GACnB;EACF,CAAC;EACD,8BAAA,eAAe,MAAM;GACnB,SAAS,8BAAA;GACT,oBAAoB,8BAAA;GACpB,sBAAsB,8BAAA;GACtB,uBAAuB,8BAAA;GACvB,wBAAwB,8BAAA;GACxB,gBAAgB,8BAAA;GAChB,gBAAgB,8BAAA;GAChB,WAAW,8BAAA;EACb,CAAC;CACH;CAEA,UAAU,MAQD;EACP,KAAK,UAAU,MAAM,YAAY;EACjC,KAAK,qBAAqB,MAAM,uBAAuB;EACvD,KAAK,uBAAuB,MAAM,yBAAyB;EAC3D,KAAK,wBAAwB,MAAM,0BAA0B;EAC7D,KAAK,yBAAyB,MAAM,QAAQ,MAAM,sBAAsB,IACpE,CACE,GAAG,IAAI,IACL,KAAK,uBAAuB,QAAQ,OAAO,OAAO,OAAO,YAAY,GAAG,SAAS,KAAK,GAAG,UAAU,GAAG,CACxG,CACF,CAAC,CAAC,MAAM,IAAI,IACZ,CAAC;EACL,KAAK,iBAAiB,MAAM,mBAAmB;EAC/C,KAAK,iBAAiB,MAAM,QAAQ,MAAM,cAAc,IACpD,KAAK,eACF,OAAO,2BAAA,oBAAoB,CAAC,CAC5B,MAAM,GAAG,GAAG,CAAC,CACb,KAAK,EAAE,WAAW,OAAO,WAAW;GAAE;GAAW;GAAO;EAAI,EAAE,IACjE,CAAC;CACP;CAEA,SAQE;EACA,OAAO;GACL,SAAS,KAAK;GACd,oBAAoB,KAAK;GACzB,sBAAsB,KAAK;GAC3B,uBAAuB,KAAK;GAC5B,wBAAwB,CAAC,GAAG,KAAK,sBAAsB;GACvD,gBAAgB,KAAK;GACrB,gBAAgB,KAAK,eAAe,KAAK,EAAE,WAAW,OAAO,WAAW;IAAE;IAAW;IAAO;GAAI,EAAE;EACpG;CACF;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
let node_crypto = require("node:crypto");
|
|
1
2
|
let node_fs_promises = require("node:fs/promises");
|
|
2
3
|
let node_path = require("node:path");
|
|
3
|
-
let node_crypto = require("node:crypto");
|
|
4
4
|
//#region src/main/dashboard-icon-cache.ts
|
|
5
5
|
var maxBytes = 2 * 1024 * 1024;
|
|
6
6
|
function boundedDashboardIcons(value) {
|