@64mb/freelens-power 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/out/main/common/power-logs.js.map +1 -1
- package/out/main/power-logs-child.js +3 -3
- package/out/main/power-logs-child.js.map +1 -1
- package/out/main/power-logs-database.js +165 -7
- package/out/main/power-logs-database.js.map +1 -1
- package/out/main/power-logs-ipc.js +12 -3
- package/out/main/power-logs-ipc.js.map +1 -1
- package/out/main/power-logs-worker.js +29 -7
- package/out/main/power-logs-worker.js.map +1 -1
- package/out/renderer/ai-diagnostic-handoff.js +2 -2
- package/out/renderer/ai-diagnostic-handoff.js.map +1 -1
- package/out/renderer/ai-extras.js +1 -1
- package/out/renderer/ai-extras.js.map +1 -1
- package/out/renderer/ai.js +4 -1
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/dashboard.js +10 -3
- package/out/renderer/dashboard.js.map +1 -1
- package/out/renderer/diagnostics-screen-finding.js +51 -0
- package/out/renderer/diagnostics-screen-finding.js.map +1 -0
- package/out/renderer/diagnostics.css.js +1 -1
- package/out/renderer/diagnostics.css.js.map +1 -1
- package/out/renderer/diagnostics.js +12 -0
- package/out/renderer/diagnostics.js.map +1 -1
- package/out/renderer/index.js +2 -0
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/pod-details-enhancements.js +106 -0
- package/out/renderer/pod-details-enhancements.js.map +1 -0
- package/out/renderer/power-log-json-cell.js +15 -14
- package/out/renderer/power-log-json-cell.js.map +1 -1
- package/out/renderer/power-log-json.js +14 -6
- package/out/renderer/power-log-json.js.map +1 -1
- package/out/renderer/power-log-sql-editor.js +31 -2
- package/out/renderer/power-log-sql-editor.js.map +1 -1
- package/out/renderer/power-logs-client.js +5 -0
- package/out/renderer/power-logs-client.js.map +1 -1
- package/out/renderer/power-logs-entrypoints.js +10 -36
- package/out/renderer/power-logs-entrypoints.js.map +1 -1
- package/out/renderer/power-logs.css.js +9 -2
- package/out/renderer/power-logs.css.js.map +1 -1
- package/out/renderer/power-logs.js +220 -91
- package/out/renderer/power-logs.js.map +1 -1
- package/out/renderer/preferences/logs-preferences.js +1 -1
- package/out/renderer/preferences/logs-preferences.js.map +1 -1
- package/out/renderer/relationship-map-finding.js +53 -0
- package/out/renderer/relationship-map-finding.js.map +1 -0
- package/out/renderer/resource-relationships.css.js +6 -0
- package/out/renderer/resource-relationships.css.js.map +1 -1
- package/out/renderer/resource-relationships.js +50 -5
- package/out/renderer/resource-relationships.js.map +1 -1
- package/out/renderer/resource-search.js +13 -3
- package/out/renderer/resource-search.js.map +1 -1
- package/out/renderer/src/common/gateway-relationships.js +8 -7
- package/out/renderer/src/common/gateway-relationships.js.map +1 -1
- package/out/renderer/src/common/power-log-json-filter-sql.js +12 -0
- package/out/renderer/src/common/power-log-json-filter-sql.js.map +1 -1
- package/out/renderer/src/common/power-log-json-preset.js +2 -2
- package/out/renderer/src/common/power-log-json-preset.js.map +1 -1
- package/out/renderer/src/common/power-logs.js.map +1 -1
- package/out/renderer/src/common/resource-relationships.js +10 -8
- package/out/renderer/src/common/resource-relationships.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/renderer/index.tsx"],"sourcesContent":["/**\n * Copyright (c) Freelens Authors. All rights reserved.\n * Licensed under MIT License. See THIRD_PARTY_LICENSES for more information.\n */\n\nimport { Common, Renderer } from \"@freelensapp/extensions\";\nimport { computed, reaction } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { LogsPreferencesStore } from \"../common/store/logs-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiChat } from \"./ai\";\nimport { startAppearanceOverride } from \"./appearance\";\nimport { startPowerButtonStyles } from \"./button-styles\";\nimport { ClusterIconsPage } from \"./cluster-icons\";\nimport { DashboardPage } from \"./dashboard\";\nimport { HpaDiagnosticsDetails } from \"./details/hpa-diagnostics-details\";\nimport { NamespaceHealthDetails } from \"./details/namespace-health-details\";\nimport { ResourceHealthDetails } from \"./details/resource-health-details\";\nimport { SecretCertificateDetails } from \"./details/secret-certificate-details\";\nimport { ServiceDiagnosticsDetails } from \"./details/service-diagnostics-details\";\nimport { DiagnosticsPage } from \"./diagnostics\";\nimport { type DiagnosticsResourceScope, focusDiagnosticsNamespace } from \"./diagnostics-state\";\nimport { SecureNodeShellMenu } from \"./menus/secure-node-shell-menu\";\nimport { startMonitoring } from \"./monitoring\";\nimport { startMonitoringCollector } from \"./monitoring-collector\";\nimport { startMonitoringHistoryCollection } from \"./monitoring-history-collection\";\nimport { NodeMonitoringDetails } from \"./node-monitoring\";\nimport { startPodMonitoring } from \"./pod-monitoring\";\nimport { PowerLogsPage } from \"./power-logs\";\nimport { PowerLogsMenu, startPowerLogsEntrypoints } from \"./power-logs-entrypoints\";\nimport { PowerPreferences } from \"./preferences/preferences\";\nimport { openPreferencesSection } from \"./preferences/section-navigation\";\nimport { startReadOnlyMode } from \"./read-only\";\nimport { ResourceRelationshipsPage } from \"./resource-relationships\";\nimport { startResourceSearch } from \"./resource-search\";\nimport { startWelcomeOverride } from \"./welcome\";\n\nimport type { ReactNode } from \"react\";\n\nconst PowerEnabled = observer(({ children }: { children: ReactNode }) =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled ? <>{children}</> : null,\n);\n\nconst RelationshipsPage = observer(() => (\n <PowerEnabled>\n <ResourceRelationshipsPage\n enabled={MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible}\n />\n </PowerEnabled>\n));\n\nexport default class FreelensPowerRenderer extends Renderer.LensExtension {\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n private stopFeatures?: () => void;\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n LogsPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = [];\n if (enabled) {\n for (const start of [\n startReadOnlyMode,\n startMonitoringCollector,\n startMonitoringHistoryCollection,\n startMonitoring,\n startPodMonitoring,\n startPowerButtonStyles,\n startAppearanceOverride,\n startWelcomeOverride,\n startAiChat,\n startResourceSearch,\n startPowerLogsEntrypoints,\n ]) {\n try {\n disposers.push(start());\n } catch {\n Common.logger.warn(\"[Freelens Power] feature could not start\", { feature: start.name });\n }\n }\n }\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n\n appPreferences = [\n {\n id: \"freelens-power-settings\",\n title: \"\",\n components: { Input: PowerPreferences, Hint: () => null },\n },\n ];\n\n globalPages = [\n {\n id: \"cluster-icons\",\n components: {\n Page: () => (\n <PowerEnabled>\n <ClusterIconsPage />\n </PowerEnabled>\n ),\n },\n },\n {\n id: \"dashboard\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DashboardPage\n onOpenPreferences={() => openPreferencesSection(\"dashboard\", () => this.navigateToPreferences())}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPages = [\n {\n id: \"power-logs\",\n components: {\n Page: () => (\n <PowerEnabled>\n <PowerLogsPage />\n </PowerEnabled>\n ),\n },\n },\n { id: \"relationships\", components: { Page: () => <RelationshipsPage /> } },\n {\n id: \"diagnostics\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DiagnosticsPage />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPageMenus = [\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().diagnosticsVisible,\n ),\n target: { pageId: \"diagnostics\" },\n title: \"Diagnostics\",\n orderNumber: 5,\n components: { Icon: () => <Renderer.Component.Icon material=\"insights\" tooltip=\"Resource diagnostics\" /> },\n },\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible,\n ),\n id: \"relationships\",\n target: { pageId: \"relationships\" },\n title: \"Relationships\",\n orderNumber: 6,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"account_tree\" tooltip=\"Resource relationships\" />,\n },\n },\n {\n id: \"power-logs\",\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n LogsPreferencesStore.getInstanceOrCreate<LogsPreferencesStore>().enabled,\n ),\n target: { pageId: \"power-logs\" },\n title: \"Power Logs\",\n orderNumber: 7,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"subject\" tooltip=\"Workload logs and SQL captures\" />,\n },\n },\n ];\n\n topBarItems = [\n {\n components: {\n Item: () => (\n <PowerEnabled>\n <Renderer.Component.Icon\n material=\"battery_charging_full\"\n className=\"freelens-power-settings-icon\"\n tooltip=\"Freelens Power settings\"\n onClick={() => this.navigateToPreferences()}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n private openDiagnostics = (namespace?: string, resourceScope?: DiagnosticsResourceScope) => {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n if (clusterId && (namespace || resourceScope)) focusDiagnosticsNamespace(clusterId, namespace, resourceScope);\n void this.navigate(\"diagnostics\");\n };\n\n kubeObjectDetailItems: Renderer.LensExtension[\"kubeObjectDetailItems\"] = [\n ...[\"Pod\", \"Deployment\", \"StatefulSet\", \"DaemonSet\", \"Node\"].map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" || kind === \"Node\" ? [\"v1\"] : [\"apps/v1\"],\n priority: 320,\n components: {\n Details: (props: Renderer.Component.KubeObjectDetailsProps) => (\n <PowerEnabled>\n <ResourceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Namespace\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NamespaceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Service\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <ServiceDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.Service} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"HorizontalPodAutoscaler\",\n apiVersions: [\"autoscaling/v1\", \"autoscaling/v2\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <HpaDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.HorizontalPodAutoscaler} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n // host order is [300 - priority], before native metrics at [-1]\n priority: 310,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NodeMonitoringDetails {...props} object={props.object as Renderer.K8sApi.Node} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Secret\",\n apiVersions: [\"v1\"],\n priority: 10,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <SecretCertificateDetails {...props} object={props.object as Renderer.K8sApi.Secret} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n kubeObjectMenuItems = [\n ...([\"Pod\", \"Deployment\", \"DaemonSet\", \"StatefulSet\", \"ReplicaSet\", \"Job\", \"CronJob\"] as const).map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" ? [\"v1\"] : kind === \"Job\" || kind === \"CronJob\" ? [\"batch/v1\"] : [\"apps/v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.KubeObject>) => (\n <PowerEnabled>\n <PowerLogsMenu {...props} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.Node>) => (\n <PowerEnabled>\n <SecureNodeShellMenu {...props} />\n </PowerEnabled>\n ),\n },\n },\n ];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/renderer/index.tsx"],"sourcesContent":["/**\n * Copyright (c) Freelens Authors. All rights reserved.\n * Licensed under MIT License. See THIRD_PARTY_LICENSES for more information.\n */\n\nimport { Common, Renderer } from \"@freelensapp/extensions\";\nimport { computed, reaction } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { LogsPreferencesStore } from \"../common/store/logs-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiChat } from \"./ai\";\nimport { startAppearanceOverride } from \"./appearance\";\nimport { startPowerButtonStyles } from \"./button-styles\";\nimport { ClusterIconsPage } from \"./cluster-icons\";\nimport { DashboardPage } from \"./dashboard\";\nimport { HpaDiagnosticsDetails } from \"./details/hpa-diagnostics-details\";\nimport { NamespaceHealthDetails } from \"./details/namespace-health-details\";\nimport { ResourceHealthDetails } from \"./details/resource-health-details\";\nimport { SecretCertificateDetails } from \"./details/secret-certificate-details\";\nimport { ServiceDiagnosticsDetails } from \"./details/service-diagnostics-details\";\nimport { DiagnosticsPage } from \"./diagnostics\";\nimport { type DiagnosticsResourceScope, focusDiagnosticsNamespace } from \"./diagnostics-state\";\nimport { SecureNodeShellMenu } from \"./menus/secure-node-shell-menu\";\nimport { startMonitoring } from \"./monitoring\";\nimport { startMonitoringCollector } from \"./monitoring-collector\";\nimport { startMonitoringHistoryCollection } from \"./monitoring-history-collection\";\nimport { NodeMonitoringDetails } from \"./node-monitoring\";\nimport { startPodDetailsEnhancements } from \"./pod-details-enhancements\";\nimport { startPodMonitoring } from \"./pod-monitoring\";\nimport { PowerLogsPage } from \"./power-logs\";\nimport { PowerLogsMenu, startPowerLogsEntrypoints } from \"./power-logs-entrypoints\";\nimport { PowerPreferences } from \"./preferences/preferences\";\nimport { openPreferencesSection } from \"./preferences/section-navigation\";\nimport { startReadOnlyMode } from \"./read-only\";\nimport { ResourceRelationshipsPage } from \"./resource-relationships\";\nimport { startResourceSearch } from \"./resource-search\";\nimport { startWelcomeOverride } from \"./welcome\";\n\nimport type { ReactNode } from \"react\";\n\nconst PowerEnabled = observer(({ children }: { children: ReactNode }) =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled ? <>{children}</> : null,\n);\n\nconst RelationshipsPage = observer(() => (\n <PowerEnabled>\n <ResourceRelationshipsPage\n enabled={MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible}\n />\n </PowerEnabled>\n));\n\nexport default class FreelensPowerRenderer extends Renderer.LensExtension {\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n private stopFeatures?: () => void;\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n LogsPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = [];\n if (enabled) {\n for (const start of [\n startReadOnlyMode,\n startMonitoringCollector,\n startMonitoringHistoryCollection,\n startMonitoring,\n startPodMonitoring,\n startPodDetailsEnhancements,\n startPowerButtonStyles,\n startAppearanceOverride,\n startWelcomeOverride,\n startAiChat,\n startResourceSearch,\n startPowerLogsEntrypoints,\n ]) {\n try {\n disposers.push(start());\n } catch {\n Common.logger.warn(\"[Freelens Power] feature could not start\", { feature: start.name });\n }\n }\n }\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n\n appPreferences = [\n {\n id: \"freelens-power-settings\",\n title: \"\",\n components: { Input: PowerPreferences, Hint: () => null },\n },\n ];\n\n globalPages = [\n {\n id: \"cluster-icons\",\n components: {\n Page: () => (\n <PowerEnabled>\n <ClusterIconsPage />\n </PowerEnabled>\n ),\n },\n },\n {\n id: \"dashboard\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DashboardPage\n onOpenPreferences={() => openPreferencesSection(\"dashboard\", () => this.navigateToPreferences())}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPages = [\n {\n id: \"power-logs\",\n components: {\n Page: () => (\n <PowerEnabled>\n <PowerLogsPage />\n </PowerEnabled>\n ),\n },\n },\n { id: \"relationships\", components: { Page: () => <RelationshipsPage /> } },\n {\n id: \"diagnostics\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DiagnosticsPage />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPageMenus = [\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().diagnosticsVisible,\n ),\n target: { pageId: \"diagnostics\" },\n title: \"Diagnostics\",\n orderNumber: 5,\n components: { Icon: () => <Renderer.Component.Icon material=\"insights\" tooltip=\"Resource diagnostics\" /> },\n },\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible,\n ),\n id: \"relationships\",\n target: { pageId: \"relationships\" },\n title: \"Relationships\",\n orderNumber: 6,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"account_tree\" tooltip=\"Resource relationships\" />,\n },\n },\n {\n id: \"power-logs\",\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n LogsPreferencesStore.getInstanceOrCreate<LogsPreferencesStore>().enabled,\n ),\n target: { pageId: \"power-logs\" },\n title: \"Power Logs\",\n orderNumber: 7,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"subject\" tooltip=\"Workload logs and SQL captures\" />,\n },\n },\n ];\n\n topBarItems = [\n {\n components: {\n Item: () => (\n <PowerEnabled>\n <Renderer.Component.Icon\n material=\"battery_charging_full\"\n className=\"freelens-power-settings-icon\"\n tooltip=\"Freelens Power settings\"\n onClick={() => this.navigateToPreferences()}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n private openDiagnostics = (namespace?: string, resourceScope?: DiagnosticsResourceScope) => {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n if (clusterId && (namespace || resourceScope)) focusDiagnosticsNamespace(clusterId, namespace, resourceScope);\n void this.navigate(\"diagnostics\");\n };\n\n kubeObjectDetailItems: Renderer.LensExtension[\"kubeObjectDetailItems\"] = [\n ...[\"Pod\", \"Deployment\", \"StatefulSet\", \"DaemonSet\", \"Node\"].map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" || kind === \"Node\" ? [\"v1\"] : [\"apps/v1\"],\n priority: 320,\n components: {\n Details: (props: Renderer.Component.KubeObjectDetailsProps) => (\n <PowerEnabled>\n <ResourceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Namespace\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NamespaceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Service\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <ServiceDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.Service} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"HorizontalPodAutoscaler\",\n apiVersions: [\"autoscaling/v1\", \"autoscaling/v2\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <HpaDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.HorizontalPodAutoscaler} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n // host order is [300 - priority], before native metrics at [-1]\n priority: 310,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NodeMonitoringDetails {...props} object={props.object as Renderer.K8sApi.Node} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Secret\",\n apiVersions: [\"v1\"],\n priority: 10,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <SecretCertificateDetails {...props} object={props.object as Renderer.K8sApi.Secret} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n kubeObjectMenuItems = [\n ...([\"Pod\", \"Deployment\", \"DaemonSet\", \"StatefulSet\", \"ReplicaSet\", \"Job\", \"CronJob\"] as const).map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" ? [\"v1\"] : kind === \"Job\" || kind === \"CronJob\" ? [\"batch/v1\"] : [\"apps/v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.KubeObject>) => (\n <PowerEnabled>\n <PowerLogsMenu {...props} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.Node>) => (\n <PowerEnabled>\n <SecureNodeShellMenu {...props} />\n </PowerEnabled>\n ),\n },\n },\n ];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
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__global_external_react_dom = require("./_virtual/_global-external_react-dom.js");
|
|
4
|
+
const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
|
|
5
|
+
//#region src/renderer/pod-details-enhancements.tsx
|
|
6
|
+
var cellMarker = "data-power-pod-name";
|
|
7
|
+
var hoverMarker = "data-power-pod-name-hover";
|
|
8
|
+
var selector = ".KubeObjectDetails :is(.DeploymentDetails, .ReplicaSetDetails, .StatefulSetDetails, .DaemonSetDetails, .JobDetails, .CronJobDetails, .ReplicationControllerDetails) .PodDetailsList .TableRow .TableCell.name a[href]";
|
|
9
|
+
function podPath(link) {
|
|
10
|
+
try {
|
|
11
|
+
const path = new URL(link.href, window.location.href).searchParams.get("kube-details");
|
|
12
|
+
return path && /^\/api\/v1\/namespaces\/[^/]+\/pods\/[^/]+$/.test(path) ? path : void 0;
|
|
13
|
+
} catch {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function startPodDetailsEnhancements() {
|
|
18
|
+
const mounted = /* @__PURE__ */ new Map();
|
|
19
|
+
const style = document.createElement("style");
|
|
20
|
+
style.dataset.freelensPower = "pod-details-enhancements";
|
|
21
|
+
style.textContent = `
|
|
22
|
+
[${cellMarker}] > .power-pod-status { display:inline-flex;align-items:center;vertical-align:middle;margin-right:8px; }
|
|
23
|
+
[${cellMarker}] > .power-pod-status .StatusBrick { margin-right:0; }
|
|
24
|
+
[${hoverMarker}]:hover { background-color:transparent!important; }
|
|
25
|
+
`;
|
|
26
|
+
document.head.append(style);
|
|
27
|
+
let stopped = false;
|
|
28
|
+
let scheduled = false;
|
|
29
|
+
const remove = (link, item) => {
|
|
30
|
+
require__global_external_react_dom.default.unmountComponentAtNode(item.host);
|
|
31
|
+
item.host.remove();
|
|
32
|
+
item.cell.removeAttribute(cellMarker);
|
|
33
|
+
for (const badge of item.badges) badge.removeAttribute(hoverMarker);
|
|
34
|
+
mounted.delete(link);
|
|
35
|
+
};
|
|
36
|
+
const update = () => {
|
|
37
|
+
scheduled = false;
|
|
38
|
+
if (stopped) return;
|
|
39
|
+
const pods = new Map(require_extensions.Renderer.K8sApi.podsStore.items.map((pod) => [pod.selfLink, pod]));
|
|
40
|
+
const links = new Set(document.querySelectorAll(selector));
|
|
41
|
+
for (const [link, item] of mounted) if (!links.has(link) || !pods.has(podPath(link) ?? "")) remove(link, item);
|
|
42
|
+
for (const link of links) {
|
|
43
|
+
const path = podPath(link);
|
|
44
|
+
const pod = path ? pods.get(path) : void 0;
|
|
45
|
+
const cell = link.closest(".TableCell.name");
|
|
46
|
+
if (!pod || !cell) continue;
|
|
47
|
+
let item = mounted.get(link);
|
|
48
|
+
if (!item) {
|
|
49
|
+
const host = document.createElement("span");
|
|
50
|
+
host.className = "power-pod-status";
|
|
51
|
+
const badges = [link.parentElement, link.firstElementChild].filter((element) => !!element && element !== cell);
|
|
52
|
+
item = {
|
|
53
|
+
host,
|
|
54
|
+
cell,
|
|
55
|
+
badges,
|
|
56
|
+
signature: ""
|
|
57
|
+
};
|
|
58
|
+
cell.setAttribute(cellMarker, "");
|
|
59
|
+
for (const badge of badges) badge.setAttribute(hoverMarker, "");
|
|
60
|
+
cell.prepend(host);
|
|
61
|
+
mounted.set(link, item);
|
|
62
|
+
}
|
|
63
|
+
const status = pod.getStatus();
|
|
64
|
+
const message = pod.getStatusMessage();
|
|
65
|
+
const signature = JSON.stringify([
|
|
66
|
+
path,
|
|
67
|
+
status,
|
|
68
|
+
message
|
|
69
|
+
]);
|
|
70
|
+
if (signature === item.signature) continue;
|
|
71
|
+
item.signature = signature;
|
|
72
|
+
require__global_external_react_dom.default.render(/* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.StatusBrick, {
|
|
73
|
+
className: status.toLowerCase(),
|
|
74
|
+
tooltip: message
|
|
75
|
+
}), item.host);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const schedule = () => {
|
|
79
|
+
if (scheduled || stopped) return;
|
|
80
|
+
scheduled = true;
|
|
81
|
+
queueMicrotask(update);
|
|
82
|
+
};
|
|
83
|
+
const observer = new MutationObserver(schedule);
|
|
84
|
+
observer.observe(document.body, {
|
|
85
|
+
subtree: true,
|
|
86
|
+
childList: true,
|
|
87
|
+
attributes: true,
|
|
88
|
+
attributeFilter: ["href"]
|
|
89
|
+
});
|
|
90
|
+
const stopReaction = require__global_external_mobx.reaction(() => [require_extensions.Renderer.Catalog.activeCluster.get()?.metadata.uid, require_extensions.Renderer.K8sApi.podsStore.items.map((pod) => [
|
|
91
|
+
pod.selfLink,
|
|
92
|
+
pod.getStatus(),
|
|
93
|
+
pod.getStatusMessage()
|
|
94
|
+
])], schedule, { fireImmediately: true });
|
|
95
|
+
return () => {
|
|
96
|
+
stopped = true;
|
|
97
|
+
observer.disconnect();
|
|
98
|
+
stopReaction();
|
|
99
|
+
for (const [link, item] of mounted) remove(link, item);
|
|
100
|
+
style.remove();
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
exports.startPodDetailsEnhancements = startPodDetailsEnhancements;
|
|
105
|
+
|
|
106
|
+
//# sourceMappingURL=pod-details-enhancements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pod-details-enhancements.js","names":[],"sources":["../../src/renderer/pod-details-enhancements.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { reaction } from \"mobx\";\nimport ReactDOM from \"react-dom\";\n\nconst cellMarker = \"data-power-pod-name\";\nconst hoverMarker = \"data-power-pod-name-hover\";\nconst selector =\n \".KubeObjectDetails :is(.DeploymentDetails, .ReplicaSetDetails, .StatefulSetDetails, .DaemonSetDetails, .JobDetails, .CronJobDetails, .ReplicationControllerDetails) .PodDetailsList .TableRow .TableCell.name a[href]\";\n\ntype Mounted = {\n host: HTMLSpanElement;\n cell: HTMLElement;\n badges: Element[];\n signature: string;\n};\n\nfunction podPath(link: HTMLAnchorElement): string | undefined {\n try {\n const path = new URL(link.href, window.location.href).searchParams.get(\"kube-details\");\n return path && /^\\/api\\/v1\\/namespaces\\/[^/]+\\/pods\\/[^/]+$/.test(path) ? path : undefined;\n } catch {\n return;\n }\n}\n\nexport function startPodDetailsEnhancements(): () => void {\n const mounted = new Map<HTMLAnchorElement, Mounted>();\n const style = document.createElement(\"style\");\n style.dataset.freelensPower = \"pod-details-enhancements\";\n style.textContent = `\n [${cellMarker}] > .power-pod-status { display:inline-flex;align-items:center;vertical-align:middle;margin-right:8px; }\n [${cellMarker}] > .power-pod-status .StatusBrick { margin-right:0; }\n [${hoverMarker}]:hover { background-color:transparent!important; }\n `;\n document.head.append(style);\n let stopped = false;\n let scheduled = false;\n const remove = (link: HTMLAnchorElement, item: Mounted) => {\n ReactDOM.unmountComponentAtNode(item.host);\n item.host.remove();\n item.cell.removeAttribute(cellMarker);\n for (const badge of item.badges) badge.removeAttribute(hoverMarker);\n mounted.delete(link);\n };\n const update = () => {\n scheduled = false;\n if (stopped) return;\n const pods = new Map(Renderer.K8sApi.podsStore.items.map((pod) => [pod.selfLink, pod]));\n const links = new Set(document.querySelectorAll<HTMLAnchorElement>(selector));\n for (const [link, item] of mounted) {\n if (!links.has(link) || !pods.has(podPath(link) ?? \"\")) remove(link, item);\n }\n for (const link of links) {\n const path = podPath(link);\n const pod = path ? pods.get(path) : undefined;\n const cell = link.closest<HTMLElement>(\".TableCell.name\");\n if (!pod || !cell) continue;\n let item = mounted.get(link);\n if (!item) {\n const host = document.createElement(\"span\");\n host.className = \"power-pod-status\";\n const badges = [link.parentElement, link.firstElementChild].filter(\n (element): element is HTMLElement => !!element && element !== cell,\n );\n item = { host, cell, badges, signature: \"\" };\n cell.setAttribute(cellMarker, \"\");\n for (const badge of badges) badge.setAttribute(hoverMarker, \"\");\n cell.prepend(host);\n mounted.set(link, item);\n }\n const status = pod.getStatus();\n const message = pod.getStatusMessage();\n const signature = JSON.stringify([path, status, message]);\n if (signature === item.signature) continue;\n item.signature = signature;\n ReactDOM.render(<Renderer.Component.StatusBrick className={status.toLowerCase()} tooltip={message} />, item.host);\n }\n };\n const schedule = () => {\n if (scheduled || stopped) return;\n scheduled = true;\n queueMicrotask(update);\n };\n const observer = new MutationObserver(schedule);\n observer.observe(document.body, { subtree: true, childList: true, attributes: true, attributeFilter: [\"href\"] });\n const stopReaction = reaction(\n () => [\n Renderer.Catalog.activeCluster.get()?.metadata.uid,\n Renderer.K8sApi.podsStore.items.map((pod) => [pod.selfLink, pod.getStatus(), pod.getStatusMessage()]),\n ],\n schedule,\n { fireImmediately: true },\n );\n return () => {\n stopped = true;\n observer.disconnect();\n stopReaction();\n for (const [link, item] of mounted) remove(link, item);\n style.remove();\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
const require__global_external_react = require("./_virtual/_global-external_react.js");
|
|
2
2
|
const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
|
|
3
3
|
const require_native_tooltip = require("./native-tooltip.js");
|
|
4
|
+
const require_date_time = require("./src/common/date-time.js");
|
|
4
5
|
const require_power_log_sql_level = require("./src/common/power-log-sql-level.js");
|
|
5
6
|
const require_power_log_json_fields = require("./power-log-json-fields.js");
|
|
6
7
|
const require_power_log_json = require("./power-log-json.js");
|
|
7
8
|
const require_power_log_message = require("./power-log-message.js");
|
|
8
9
|
let electron = require("electron");
|
|
9
10
|
//#region src/renderer/power-log-json-cell.tsx
|
|
10
|
-
function LogJsonCell({ value, column, rawValue, Icon
|
|
11
|
+
function LogJsonCell({ value, column, rawValue, Icon }) {
|
|
11
12
|
const preview = require__global_external_react.useMemo(() => {
|
|
12
13
|
if (value === null || !/^[\s]*[\[{]/.test(value)) return null;
|
|
13
14
|
try {
|
|
14
15
|
const parsed = JSON.parse(value);
|
|
15
16
|
if (!parsed || typeof parsed !== "object") return null;
|
|
16
17
|
const compact = require_power_log_json_fields.compactJsonLiteral(value);
|
|
17
|
-
return {
|
|
18
|
-
text: compact.length > 2048 ? `${compact.slice(0, 2048)}…` : compact,
|
|
19
|
-
full: compact,
|
|
20
|
-
fieldsEnabled: !require_power_log_json_fields.jsonHasDuplicateKeys(value)
|
|
21
|
-
};
|
|
18
|
+
return { text: compact.length > 2048 ? `${compact.slice(0, 2048)}…` : compact };
|
|
22
19
|
} catch {
|
|
23
20
|
return null;
|
|
24
21
|
}
|
|
25
22
|
}, [value]);
|
|
26
23
|
const [feedback, setFeedback] = require__global_external_react.useState("");
|
|
27
24
|
require__global_external_react.useEffect(() => setFeedback(""), [value]);
|
|
25
|
+
if ((column?.toLowerCase() === "timestamp" || column?.toLowerCase() === "minute") && typeof rawValue === "number" && Number.isFinite(new Date(rawValue).getTime())) {
|
|
26
|
+
const formatted = require_date_time.formatDateTime(rawValue);
|
|
27
|
+
return /* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
|
|
28
|
+
title: `${formatted} · ${rawValue}`,
|
|
29
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
30
|
+
className: "power-logs-cell",
|
|
31
|
+
children: column?.toLowerCase() === "minute" ? formatted.slice(0, -3) : formatted.slice(-8)
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
}
|
|
28
35
|
if (preview === null) {
|
|
29
36
|
const level = require_power_log_sql_level.sqlCellLevel(column ?? "", rawValue === void 0 ? value : rawValue);
|
|
30
37
|
return /* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
|
|
@@ -42,13 +49,7 @@ function LogJsonCell({ value, column, rawValue, Icon, onFilter }) {
|
|
|
42
49
|
return /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
43
50
|
className: "power-logs-cell power-logs-json-cell",
|
|
44
51
|
children: [
|
|
45
|
-
/* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_json.LogJson, {
|
|
46
|
-
text: preview.text,
|
|
47
|
-
fieldText: preview.full,
|
|
48
|
-
fieldsEnabled: preview.fieldsEnabled,
|
|
49
|
-
Icon,
|
|
50
|
-
onFilter
|
|
51
|
-
}),
|
|
52
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_json.LogJson, { text: preview.text }),
|
|
52
53
|
/* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
|
|
53
54
|
title: feedback || "Copy JSON",
|
|
54
55
|
children: /* @__PURE__ */ require_jsx_runtime.jsx("button", {
|
|
@@ -60,7 +61,7 @@ function LogJsonCell({ value, column, rawValue, Icon, onFilter }) {
|
|
|
60
61
|
onClick: (event) => {
|
|
61
62
|
event.stopPropagation();
|
|
62
63
|
try {
|
|
63
|
-
electron.clipboard.writeText(value);
|
|
64
|
+
electron.clipboard.writeText(require_power_log_json_fields.formatJsonLiteral(value));
|
|
64
65
|
setFeedback("Copied");
|
|
65
66
|
} catch {
|
|
66
67
|
setFeedback("Unable to copy JSON");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"power-log-json-cell.js","names":[],"sources":["../../src/renderer/power-log-json-cell.tsx"],"sourcesContent":["import { clipboard } from \"electron\";\nimport { type ComponentType, useEffect, useMemo, useState } from \"react\";\nimport { sqlCellLevel } from \"../common/power-log-sql-level\";\nimport { NativeTooltip } from \"./native-tooltip\";\nimport { LogJson } from \"./power-log-json\";\nimport { compactJsonLiteral,
|
|
1
|
+
{"version":3,"file":"power-log-json-cell.js","names":[],"sources":["../../src/renderer/power-log-json-cell.tsx"],"sourcesContent":["import { clipboard } from \"electron\";\nimport { type ComponentType, useEffect, useMemo, useState } from \"react\";\nimport { formatDateTime } from \"../common/date-time\";\nimport { sqlCellLevel } from \"../common/power-log-sql-level\";\nimport { NativeTooltip } from \"./native-tooltip\";\nimport { LogJson } from \"./power-log-json\";\nimport { compactJsonLiteral, formatJsonLiteral } from \"./power-log-json-fields\";\nimport { LogMessage } from \"./power-log-message\";\n\nimport type { LogCell } from \"../common/power-logs\";\n\nexport function LogJsonCell({\n value,\n column,\n rawValue,\n Icon,\n}: {\n value: string | null;\n message?: boolean;\n column?: string;\n rawValue?: LogCell;\n Icon: ComponentType<{ material: string; size?: number }>;\n}) {\n const preview = useMemo(() => {\n if (value === null || !/^[\\s]*[\\[{]/.test(value)) return null;\n try {\n const parsed: unknown = JSON.parse(value);\n if (!parsed || typeof parsed !== \"object\") return null;\n const compact = compactJsonLiteral(value);\n return {\n text: compact.length > 2048 ? `${compact.slice(0, 2048)}…` : compact,\n };\n } catch {\n return null;\n }\n }, [value]);\n const [feedback, setFeedback] = useState(\"\");\n useEffect(() => setFeedback(\"\"), [value]);\n if (\n (column?.toLowerCase() === \"timestamp\" || column?.toLowerCase() === \"minute\") &&\n typeof rawValue === \"number\" &&\n Number.isFinite(new Date(rawValue).getTime())\n ) {\n const formatted = formatDateTime(rawValue);\n return (\n <NativeTooltip title={`${formatted} · ${rawValue}`}>\n <span className=\"power-logs-cell\">\n {column?.toLowerCase() === \"minute\" ? formatted.slice(0, -3) : formatted.slice(-8)}\n </span>\n </NativeTooltip>\n );\n }\n if (preview === null) {\n const level = sqlCellLevel(column ?? \"\", rawValue === undefined ? value : rawValue);\n return (\n <NativeTooltip title={value ?? \"NULL\"}>\n <span className=\"power-logs-cell\">\n {value === null ? (\n \"NULL\"\n ) : level !== \"unknown\" ? (\n <span className=\"power-logs-level-label\" data-level={level}>\n {typeof rawValue === \"number\" ? value : value.toUpperCase()}\n </span>\n ) : (\n <LogMessage text={value} />\n )}\n </span>\n </NativeTooltip>\n );\n }\n return (\n <div className=\"power-logs-cell power-logs-json-cell\">\n <LogJson text={preview.text} />\n <NativeTooltip title={feedback || \"Copy JSON\"}>\n <button\n type=\"button\"\n className=\"power-logs-json-copy\"\n aria-label=\"Copy JSON\"\n onKeyDown={(event) => event.stopPropagation()}\n onKeyUp={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation();\n try {\n clipboard.writeText(formatJsonLiteral(value!));\n setFeedback(\"Copied\");\n } catch {\n setFeedback(\"Unable to copy JSON\");\n }\n }}\n >\n <Icon material={feedback === \"Copied\" ? \"check\" : \"content_copy\"} size={14} />\n </button>\n </NativeTooltip>\n <span className=\"power-logs-json-copy-feedback\" role=\"status\" aria-live=\"polite\">\n {feedback}\n </span>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,YAAY,EAC1B,OACA,QACA,UACA,QAOC;CACD,MAAM,UAAU,+BAAA,cAAc;EAC5B,IAAI,UAAU,QAAQ,CAAC,cAAc,KAAK,KAAK,GAAG,OAAO;EACzD,IAAI;GACF,MAAM,SAAkB,KAAK,MAAM,KAAK;GACxC,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU,OAAO;GAClD,MAAM,UAAU,8BAAA,mBAAmB,KAAK;GACxC,OAAO,EACL,MAAM,QAAQ,SAAS,OAAO,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,QAC/D;EACF,QAAQ;GACN,OAAO;EACT;CACF,GAAG,CAAC,KAAK,CAAC;CACV,MAAM,CAAC,UAAU,eAAe,+BAAA,SAAS,EAAE;CAC3C,+BAAA,gBAAgB,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC;CACxC,KACG,QAAQ,YAAY,MAAM,eAAe,QAAQ,YAAY,MAAM,aACpE,OAAO,aAAa,YACpB,OAAO,SAAS,IAAI,KAAK,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAC5C;EACA,MAAM,YAAY,kBAAA,eAAe,QAAQ;EACzC,OACE,oCAAA,IAAC,uBAAA,eAAD;GAAe,OAAO,GAAG,UAAU,KAAK;aACtC,oCAAA,IAAC,QAAD;IAAM,WAAU;cACb,QAAQ,YAAY,MAAM,WAAW,UAAU,MAAM,GAAG,EAAE,IAAI,UAAU,MAAM,EAAE;GAC7E,CAAA;EACO,CAAA;CAEnB;CACA,IAAI,YAAY,MAAM;EACpB,MAAM,QAAQ,4BAAA,aAAa,UAAU,IAAI,aAAa,KAAA,IAAY,QAAQ,QAAQ;EAClF,OACE,oCAAA,IAAC,uBAAA,eAAD;GAAe,OAAO,SAAS;aAC7B,oCAAA,IAAC,QAAD;IAAM,WAAU;cACb,UAAU,OACT,SACE,UAAU,YACZ,oCAAA,IAAC,QAAD;KAAM,WAAU;KAAyB,cAAY;eAClD,OAAO,aAAa,WAAW,QAAQ,MAAM,YAAY;IACtD,CAAA,IAEN,oCAAA,IAAC,0BAAA,YAAD,EAAY,MAAM,MAAQ,CAAA;GAExB,CAAA;EACO,CAAA;CAEnB;CACA,OACE,oCAAA,KAAC,OAAD;EAAK,WAAU;YAAf;GACE,oCAAA,IAAC,uBAAA,SAAD,EAAS,MAAM,QAAQ,KAAO,CAAA;GAC9B,oCAAA,IAAC,uBAAA,eAAD;IAAe,OAAO,YAAY;cAChC,oCAAA,IAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,cAAW;KACX,YAAY,UAAU,MAAM,gBAAgB;KAC5C,UAAU,UAAU,MAAM,gBAAgB;KAC1C,UAAU,UAAU;MAClB,MAAM,gBAAgB;MACtB,IAAI;OACF,SAAA,UAAU,UAAU,8BAAA,kBAAkB,KAAM,CAAC;OAC7C,YAAY,QAAQ;MACtB,QAAQ;OACN,YAAY,qBAAqB;MACnC;KACF;eAEA,oCAAA,IAAC,MAAD;MAAM,UAAU,aAAa,WAAW,UAAU;MAAgB,MAAM;KAAK,CAAA;IACvE,CAAA;GACK,CAAA;GACf,oCAAA,IAAC,QAAD;IAAM,WAAU;IAAgC,MAAK;IAAS,aAAU;cACrE;GACG,CAAA;EACH;;AAET"}
|
|
@@ -13,7 +13,6 @@ var fieldButtonStyle = {
|
|
|
13
13
|
border: 0,
|
|
14
14
|
borderRadius: 0,
|
|
15
15
|
background: "transparent",
|
|
16
|
-
color: "inherit",
|
|
17
16
|
display: "inline-flex",
|
|
18
17
|
alignItems: "center",
|
|
19
18
|
justifyContent: "center",
|
|
@@ -58,6 +57,8 @@ function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }) {
|
|
|
58
57
|
clearTimeout(leaveTimer.current);
|
|
59
58
|
const rect = element.getBoundingClientRect();
|
|
60
59
|
let lineRight = rect.right;
|
|
60
|
+
let actionTop = rect.top;
|
|
61
|
+
let actionHeight = Math.min(rect.height, Number.parseFloat(getComputedStyle(element).lineHeight) || 20);
|
|
61
62
|
const pre = element.closest("pre");
|
|
62
63
|
if (pre) {
|
|
63
64
|
const lineEnd = text.indexOf("\n", start);
|
|
@@ -72,7 +73,13 @@ function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }) {
|
|
|
72
73
|
range.setStart(element, 0);
|
|
73
74
|
range.setEnd(node, remaining);
|
|
74
75
|
if (typeof range.getClientRects === "function") {
|
|
75
|
-
|
|
76
|
+
const fragments = Array.from(range.getClientRects()).filter((fragment) => fragment.width > 0 && fragment.height > 0);
|
|
77
|
+
if (fragments.length) {
|
|
78
|
+
actionTop = Math.max(...fragments.map((fragment) => fragment.top));
|
|
79
|
+
const lastLine = fragments.filter((fragment) => Math.abs(fragment.top - actionTop) < 1);
|
|
80
|
+
lineRight = Math.max(...lastLine.map((fragment) => fragment.right));
|
|
81
|
+
actionHeight = lastLine[0].height;
|
|
82
|
+
}
|
|
76
83
|
}
|
|
77
84
|
break;
|
|
78
85
|
}
|
|
@@ -84,7 +91,7 @@ function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }) {
|
|
|
84
91
|
text: identity,
|
|
85
92
|
lineTop: rect.top,
|
|
86
93
|
x: Math.max(4, Math.min(lineRight + 4, visibleRight - 64)),
|
|
87
|
-
y: Math.max(0, Math.min(
|
|
94
|
+
y: Math.max(0, Math.min(actionTop + (actionHeight - 20) / 2, window.innerHeight - 20))
|
|
88
95
|
});
|
|
89
96
|
setFeedback("");
|
|
90
97
|
};
|
|
@@ -141,6 +148,7 @@ function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }) {
|
|
|
141
148
|
}
|
|
142
149
|
},
|
|
143
150
|
children: [pre, selected && /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
151
|
+
className: "power-log-json-actions",
|
|
144
152
|
role: "toolbar",
|
|
145
153
|
"aria-label": "JSON field actions",
|
|
146
154
|
style: {
|
|
@@ -178,7 +186,7 @@ function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }) {
|
|
|
178
186
|
},
|
|
179
187
|
children: Icon ? /* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
180
188
|
material: "content_copy",
|
|
181
|
-
size:
|
|
189
|
+
size: 12,
|
|
182
190
|
tooltip: "Copy value"
|
|
183
191
|
}) : "⧉"
|
|
184
192
|
}),
|
|
@@ -193,7 +201,7 @@ function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }) {
|
|
|
193
201
|
}),
|
|
194
202
|
children: Icon ? /* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
195
203
|
material: "filter_alt",
|
|
196
|
-
size:
|
|
204
|
+
size: 12,
|
|
197
205
|
tooltip: "Include value"
|
|
198
206
|
}) : "="
|
|
199
207
|
}), /* @__PURE__ */ require_jsx_runtime.jsx("button", {
|
|
@@ -207,7 +215,7 @@ function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }) {
|
|
|
207
215
|
}),
|
|
208
216
|
children: Icon ? /* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
209
217
|
material: "filter_alt_off",
|
|
210
|
-
size:
|
|
218
|
+
size: 12,
|
|
211
219
|
tooltip: "Exclude value"
|
|
212
220
|
}) : "!="
|
|
213
221
|
})] }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"power-log-json.js","names":[],"sources":["../../src/renderer/power-log-json.tsx"],"sourcesContent":["import { clipboard } from \"electron\";\nimport { type ComponentType, type CSSProperties, type ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport { type JsonField, jsonFieldLiteral, jsonFields, maxJsonTokens } from \"./power-log-json-fields\";\n\nimport type { JsonFieldFilter } from \"../common/power-log-field-filters\";\n\nexport interface LogJsonProps {\n text: string;\n fieldText?: string;\n fieldsEnabled?: boolean;\n Icon?: ComponentType<{ material: string; size?: number; tooltip?: string }>;\n onFilter?: (filter: JsonFieldFilter) => void;\n}\n\nconst fieldButtonStyle: CSSProperties = {\n width: 20,\n height: 20,\n minHeight: 0,\n minWidth: 0,\n padding: 0,\n margin: 0,\n border: 0,\n borderRadius: 0,\n background: \"transparent\",\n color: \"inherit\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n};\n\nexport function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }: LogJsonProps) {\n const leaveTimer = useRef<ReturnType<typeof setTimeout>>();\n const hoverTimer = useRef<ReturnType<typeof setTimeout>>();\n const keepOpen = () => {\n clearTimeout(leaveTimer.current);\n clearTimeout(hoverTimer.current);\n };\n useEffect(\n () => () => {\n clearTimeout(leaveTimer.current);\n clearTimeout(hoverTimer.current);\n },\n [],\n );\n const identity = fieldText ?? text;\n const interactive = fieldsEnabled && Boolean(Icon || onFilter);\n const fields = useMemo(\n () => (interactive ? jsonFields(identity) : new Map<number, JsonField>()),\n [identity, interactive],\n );\n const [active, setActive] = useState<{ field: JsonField; text: string; x: number; y: number; lineTop: number }>();\n const activeField = useRef(active);\n activeField.current = active;\n const [feedback, setFeedback] = useState(\"\");\n const selected = fieldsEnabled && active?.text === identity ? active : undefined;\n const tokens = useMemo(() => {\n const tokens: ReactNode[] = [];\n const pattern = /\"(?:\\\\.|[^\"\\\\])*\"(?:\\s*:)?|\\b(?:true|false|null)\\b|-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|[\\[{]/g;\n let cursor = 0;\n let count = 0;\n for (const match of text.matchAll(pattern)) {\n if (++count > maxJsonTokens) break;\n const start = match.index!;\n tokens.push(text.slice(cursor, start));\n const value = match[0];\n const key = value.startsWith('\"') && value.endsWith(\":\");\n const kind = key\n ? \"key\"\n : value.startsWith('\"')\n ? \"string\"\n : /^(true|false|null)$/.test(value)\n ? \"literal\"\n : /^[\\[{]$/.test(value)\n ? undefined\n : \"number\";\n const field = fields.get(start);\n const activate = (element: HTMLElement) => {\n if (!field) return;\n clearTimeout(leaveTimer.current);\n const rect = element.getBoundingClientRect();\n let lineRight = rect.right;\n const pre = element.closest(\"pre\");\n if (pre) {\n const lineEnd = text.indexOf(\"\\n\", start);\n let remaining = lineEnd < 0 ? text.length : lineEnd;\n const walker = document.createTreeWalker(pre, NodeFilter.SHOW_TEXT);\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n if (remaining > (node.textContent?.length ?? 0)) {\n remaining -= node.textContent?.length ?? 0;\n continue;\n }\n const range = document.createRange();\n range.setStart(element, 0);\n range.setEnd(node, remaining);\n if (typeof range.getClientRects === \"function\") {\n for (const fragment of Array.from(range.getClientRects())) {\n if (Math.abs(fragment.top - rect.top) < Math.max(1, rect.height / 2)) {\n lineRight = Math.max(lineRight, fragment.right);\n }\n }\n }\n break;\n }\n }\n const wrapperRight = element.closest(\".power-log-json-fields\")?.getBoundingClientRect().right;\n const visibleRight = Math.min(\n window.innerWidth,\n wrapperRight && wrapperRight > 0 ? wrapperRight : window.innerWidth,\n );\n setActive({\n field,\n text: identity,\n lineTop: rect.top,\n x: Math.max(4, Math.min(lineRight + 4, visibleRight - 64)),\n y: Math.max(0, Math.min(rect.top, window.innerHeight - 20)),\n });\n setFeedback(\"\");\n };\n tokens.push(\n <span\n key={start}\n data-token={kind}\n tabIndex={field ? 0 : undefined}\n onMouseEnter={\n field\n ? (event) => {\n keepOpen();\n const element = event.currentTarget;\n const rect = element.getBoundingClientRect();\n if (\n activeField.current?.text === identity &&\n activeField.current.field !== field &&\n Math.abs(activeField.current.lineTop - rect.top) < 1\n ) {\n hoverTimer.current = setTimeout(() => activate(element), 180);\n } else activate(element);\n }\n : undefined\n }\n onMouseLeave={field ? () => clearTimeout(hoverTimer.current) : undefined}\n onFocus={\n field\n ? (event) => {\n keepOpen();\n activate(event.currentTarget);\n }\n : undefined\n }\n onKeyDown={\n field\n ? (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n event.stopPropagation();\n event.currentTarget\n .closest(\".power-log-json-fields\")\n ?.querySelector<HTMLButtonElement>('[role=\"toolbar\"] button')\n ?.focus();\n }\n }\n : undefined\n }\n >\n {key ? value.slice(0, -1) : value}\n </span>,\n );\n if (key) tokens.push(\":\");\n cursor = start + value.length;\n }\n tokens.push(text.slice(cursor));\n return tokens;\n }, [text, fields, identity]);\n const pre = <pre className=\"power-log-json\">{tokens}</pre>;\n if (!Icon && !onFilter) return pre;\n return (\n <div\n className=\"power-log-json-fields\"\n style={{ paddingRight: 76 }}\n onMouseEnter={keepOpen}\n onMouseLeave={() => {\n leaveTimer.current = setTimeout(() => setActive(undefined), 150);\n }}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node)) setActive(undefined);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.stopPropagation();\n setActive(undefined);\n }\n }}\n >\n {pre}\n {selected && (\n <div\n role=\"toolbar\"\n aria-label=\"JSON field actions\"\n style={{\n position: \"fixed\",\n left: selected.x,\n top: selected.y,\n zIndex: 1000,\n display: \"flex\",\n gap: 2,\n padding: 0,\n background: \"transparent\",\n border: 0,\n alignItems: \"center\",\n height: 20,\n }}\n onMouseEnter={keepOpen}\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => {\n event.stopPropagation();\n if (event.key === \"Escape\") setActive(undefined);\n }}\n >\n <button\n type=\"button\"\n style={fieldButtonStyle}\n aria-label=\"Copy value\"\n onClick={() => {\n try {\n const value = selected.field.value;\n clipboard.writeText(typeof value === \"string\" ? value : jsonFieldLiteral(identity, selected.field));\n setFeedback(\"Copied\");\n } catch {\n setFeedback(\"Copy failed\");\n }\n }}\n >\n {Icon ? <Icon material=\"content_copy\" size={14} tooltip=\"Copy value\" /> : \"⧉\"}\n </button>\n {onFilter && (\n <>\n <button\n type=\"button\"\n style={fieldButtonStyle}\n aria-label=\"Include value\"\n onClick={() => onFilter({ path: selected.field.path, value: selected.field.value, operator: \"eq\" })}\n >\n {Icon ? <Icon material=\"filter_alt\" size={14} tooltip=\"Include value\" /> : \"=\"}\n </button>\n <button\n type=\"button\"\n style={fieldButtonStyle}\n aria-label=\"Exclude value\"\n onClick={() => onFilter({ path: selected.field.path, value: selected.field.value, operator: \"neq\" })}\n >\n {Icon ? <Icon material=\"filter_alt_off\" size={14} tooltip=\"Exclude value\" /> : \"!=\"}\n </button>\n </>\n )}\n {feedback && (\n <span role=\"status\" style={{ position: \"absolute\", top: 22, right: 0, whiteSpace: \"nowrap\" }}>\n {feedback}\n </span>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"power-log-json.js","names":[],"sources":["../../src/renderer/power-log-json.tsx"],"sourcesContent":["import { clipboard } from \"electron\";\nimport { type ComponentType, type CSSProperties, type ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport { type JsonField, jsonFieldLiteral, jsonFields, maxJsonTokens } from \"./power-log-json-fields\";\n\nimport type { JsonFieldFilter } from \"../common/power-log-field-filters\";\n\nexport interface LogJsonProps {\n text: string;\n fieldText?: string;\n fieldsEnabled?: boolean;\n Icon?: ComponentType<{ material: string; size?: number; tooltip?: string }>;\n onFilter?: (filter: JsonFieldFilter) => void;\n}\n\nconst fieldButtonStyle: CSSProperties = {\n width: 20,\n height: 20,\n minHeight: 0,\n minWidth: 0,\n padding: 0,\n margin: 0,\n border: 0,\n borderRadius: 0,\n background: \"transparent\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n};\n\nexport function LogJson({ text, fieldText, fieldsEnabled = true, Icon, onFilter }: LogJsonProps) {\n const leaveTimer = useRef<ReturnType<typeof setTimeout>>();\n const hoverTimer = useRef<ReturnType<typeof setTimeout>>();\n const keepOpen = () => {\n clearTimeout(leaveTimer.current);\n clearTimeout(hoverTimer.current);\n };\n useEffect(\n () => () => {\n clearTimeout(leaveTimer.current);\n clearTimeout(hoverTimer.current);\n },\n [],\n );\n const identity = fieldText ?? text;\n const interactive = fieldsEnabled && Boolean(Icon || onFilter);\n const fields = useMemo(\n () => (interactive ? jsonFields(identity) : new Map<number, JsonField>()),\n [identity, interactive],\n );\n const [active, setActive] = useState<{ field: JsonField; text: string; x: number; y: number; lineTop: number }>();\n const activeField = useRef(active);\n activeField.current = active;\n const [feedback, setFeedback] = useState(\"\");\n const selected = fieldsEnabled && active?.text === identity ? active : undefined;\n const tokens = useMemo(() => {\n const tokens: ReactNode[] = [];\n const pattern = /\"(?:\\\\.|[^\"\\\\])*\"(?:\\s*:)?|\\b(?:true|false|null)\\b|-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|[\\[{]/g;\n let cursor = 0;\n let count = 0;\n for (const match of text.matchAll(pattern)) {\n if (++count > maxJsonTokens) break;\n const start = match.index!;\n tokens.push(text.slice(cursor, start));\n const value = match[0];\n const key = value.startsWith('\"') && value.endsWith(\":\");\n const kind = key\n ? \"key\"\n : value.startsWith('\"')\n ? \"string\"\n : /^(true|false|null)$/.test(value)\n ? \"literal\"\n : /^[\\[{]$/.test(value)\n ? undefined\n : \"number\";\n const field = fields.get(start);\n const activate = (element: HTMLElement) => {\n if (!field) return;\n clearTimeout(leaveTimer.current);\n const rect = element.getBoundingClientRect();\n let lineRight = rect.right;\n let actionTop = rect.top;\n let actionHeight = Math.min(rect.height, Number.parseFloat(getComputedStyle(element).lineHeight) || 20);\n const pre = element.closest(\"pre\");\n if (pre) {\n const lineEnd = text.indexOf(\"\\n\", start);\n let remaining = lineEnd < 0 ? text.length : lineEnd;\n const walker = document.createTreeWalker(pre, NodeFilter.SHOW_TEXT);\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n if (remaining > (node.textContent?.length ?? 0)) {\n remaining -= node.textContent?.length ?? 0;\n continue;\n }\n const range = document.createRange();\n range.setStart(element, 0);\n range.setEnd(node, remaining);\n if (typeof range.getClientRects === \"function\") {\n const fragments = Array.from(range.getClientRects()).filter(\n (fragment) => fragment.width > 0 && fragment.height > 0,\n );\n if (fragments.length) {\n actionTop = Math.max(...fragments.map((fragment) => fragment.top));\n const lastLine = fragments.filter((fragment) => Math.abs(fragment.top - actionTop) < 1);\n lineRight = Math.max(...lastLine.map((fragment) => fragment.right));\n actionHeight = lastLine[0].height;\n }\n }\n break;\n }\n }\n const wrapperRight = element.closest(\".power-log-json-fields\")?.getBoundingClientRect().right;\n const visibleRight = Math.min(\n window.innerWidth,\n wrapperRight && wrapperRight > 0 ? wrapperRight : window.innerWidth,\n );\n setActive({\n field,\n text: identity,\n lineTop: rect.top,\n x: Math.max(4, Math.min(lineRight + 4, visibleRight - 64)),\n y: Math.max(0, Math.min(actionTop + (actionHeight - 20) / 2, window.innerHeight - 20)),\n });\n setFeedback(\"\");\n };\n tokens.push(\n <span\n key={start}\n data-token={kind}\n tabIndex={field ? 0 : undefined}\n onMouseEnter={\n field\n ? (event) => {\n keepOpen();\n const element = event.currentTarget;\n const rect = element.getBoundingClientRect();\n if (\n activeField.current?.text === identity &&\n activeField.current.field !== field &&\n Math.abs(activeField.current.lineTop - rect.top) < 1\n ) {\n hoverTimer.current = setTimeout(() => activate(element), 180);\n } else activate(element);\n }\n : undefined\n }\n onMouseLeave={field ? () => clearTimeout(hoverTimer.current) : undefined}\n onFocus={\n field\n ? (event) => {\n keepOpen();\n activate(event.currentTarget);\n }\n : undefined\n }\n onKeyDown={\n field\n ? (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n event.stopPropagation();\n event.currentTarget\n .closest(\".power-log-json-fields\")\n ?.querySelector<HTMLButtonElement>('[role=\"toolbar\"] button')\n ?.focus();\n }\n }\n : undefined\n }\n >\n {key ? value.slice(0, -1) : value}\n </span>,\n );\n if (key) tokens.push(\":\");\n cursor = start + value.length;\n }\n tokens.push(text.slice(cursor));\n return tokens;\n }, [text, fields, identity]);\n const pre = <pre className=\"power-log-json\">{tokens}</pre>;\n if (!Icon && !onFilter) return pre;\n return (\n <div\n className=\"power-log-json-fields\"\n style={{ paddingRight: 76 }}\n onMouseEnter={keepOpen}\n onMouseLeave={() => {\n leaveTimer.current = setTimeout(() => setActive(undefined), 150);\n }}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node)) setActive(undefined);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.stopPropagation();\n setActive(undefined);\n }\n }}\n >\n {pre}\n {selected && (\n <div\n className=\"power-log-json-actions\"\n role=\"toolbar\"\n aria-label=\"JSON field actions\"\n style={{\n position: \"fixed\",\n left: selected.x,\n top: selected.y,\n zIndex: 1000,\n display: \"flex\",\n gap: 2,\n padding: 0,\n background: \"transparent\",\n border: 0,\n alignItems: \"center\",\n height: 20,\n }}\n onMouseEnter={keepOpen}\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => {\n event.stopPropagation();\n if (event.key === \"Escape\") setActive(undefined);\n }}\n >\n <button\n type=\"button\"\n style={fieldButtonStyle}\n aria-label=\"Copy value\"\n onClick={() => {\n try {\n const value = selected.field.value;\n clipboard.writeText(typeof value === \"string\" ? value : jsonFieldLiteral(identity, selected.field));\n setFeedback(\"Copied\");\n } catch {\n setFeedback(\"Copy failed\");\n }\n }}\n >\n {Icon ? <Icon material=\"content_copy\" size={12} tooltip=\"Copy value\" /> : \"⧉\"}\n </button>\n {onFilter && (\n <>\n <button\n type=\"button\"\n style={fieldButtonStyle}\n aria-label=\"Include value\"\n onClick={() => onFilter({ path: selected.field.path, value: selected.field.value, operator: \"eq\" })}\n >\n {Icon ? <Icon material=\"filter_alt\" size={12} tooltip=\"Include value\" /> : \"=\"}\n </button>\n <button\n type=\"button\"\n style={fieldButtonStyle}\n aria-label=\"Exclude value\"\n onClick={() => onFilter({ path: selected.field.path, value: selected.field.value, operator: \"neq\" })}\n >\n {Icon ? <Icon material=\"filter_alt_off\" size={12} tooltip=\"Exclude value\" /> : \"!=\"}\n </button>\n </>\n )}\n {feedback && (\n <span role=\"status\" style={{ position: \"absolute\", top: 22, right: 0, whiteSpace: \"nowrap\" }}>\n {feedback}\n </span>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -26,7 +26,7 @@ function tokenizeSql(value) {
|
|
|
26
26
|
return tokens;
|
|
27
27
|
}
|
|
28
28
|
var styles = `
|
|
29
|
-
.power-logs .power-logs-sql-editor{position:relative;box-sizing:border-box;width:100%;height:56px;min-height:48px;max-height:max
|
|
29
|
+
.power-logs .power-logs-sql-editor{position:relative;box-sizing:border-box;width:100%;height:56px;min-height:48px;max-height:var(--sql-content-max-height,120px);flex-shrink:0;resize:vertical;overflow:hidden;border:1px solid var(--borderColor);border-radius:4px;background:var(--inputControlBackground,var(--contentColor));--sql-string:#e6a28c;--sql-number:#98c78e;--sql-function:#81b9e6;--sql-identifier:var(--textColorPrimary)}
|
|
30
30
|
.power-logs .power-logs-sql-editor::-webkit-resizer{border:0;background:linear-gradient(135deg,transparent 45%,var(--borderColor) 46% 53%,transparent 54% 70%,var(--borderColor) 71% 78%,transparent 79%) center/10px 10px no-repeat}
|
|
31
31
|
.theme-light .power-logs-sql-editor{--sql-string:#9e2b1a;--sql-number:#17642d;--sql-function:#005a9e;--sql-identifier:#684c9b}
|
|
32
32
|
.power-logs .power-logs-sql-editor>textarea,.power-logs .power-logs-sql-editor>pre{position:absolute;inset:0;box-sizing:border-box;width:100%;height:100%;min-height:0;max-height:none;margin:0;padding:4px 8px;border:0;border-radius:0;font:12px/1.6 var(--font-monospace,monospace);letter-spacing:normal;white-space:pre-wrap;overflow-wrap:anywhere;tab-size:2;overflow:auto;scrollbar-gutter:stable;resize:none}
|
|
@@ -40,7 +40,8 @@ var styles = `
|
|
|
40
40
|
.power-logs-sql-editor [data-sql-token=number]{color:var(--sql-number)}
|
|
41
41
|
.power-logs-sql-editor [data-sql-token=comment]{color:var(--textColorSecondary)}
|
|
42
42
|
`;
|
|
43
|
-
function SqlEditor({ id, value, onChange }) {
|
|
43
|
+
function SqlEditor({ id, value, onChange, fitVersion = 0 }) {
|
|
44
|
+
const fitted = require__global_external_react.useRef(0);
|
|
44
45
|
const textarea = require__global_external_react.useRef(null);
|
|
45
46
|
const highlight = require__global_external_react.useRef(null);
|
|
46
47
|
const tokens = require__global_external_react.useMemo(() => tokenizeSql(value), [value]);
|
|
@@ -50,6 +51,34 @@ function SqlEditor({ id, value, onChange }) {
|
|
|
50
51
|
highlight.current.scrollLeft = textarea.current.scrollLeft;
|
|
51
52
|
};
|
|
52
53
|
require__global_external_react.useLayoutEffect(syncScroll, [value]);
|
|
54
|
+
require__global_external_react.useLayoutEffect(() => {
|
|
55
|
+
const pre = highlight.current;
|
|
56
|
+
const editor = pre?.parentElement;
|
|
57
|
+
if (!pre || !editor) return;
|
|
58
|
+
const measure = () => {
|
|
59
|
+
pre.style.height = "auto";
|
|
60
|
+
pre.style.bottom = "auto";
|
|
61
|
+
const height = pre.getBoundingClientRect().height;
|
|
62
|
+
pre.style.removeProperty("height");
|
|
63
|
+
pre.style.removeProperty("bottom");
|
|
64
|
+
editor.style.setProperty("--sql-content-max-height", `${Math.max(120, Math.min(240, Math.ceil(height) + 10))}px`);
|
|
65
|
+
if (fitVersion !== fitted.current) {
|
|
66
|
+
editor.style.height = `${Math.max(48, Math.min(240, Math.ceil(height) + 2))}px`;
|
|
67
|
+
fitted.current = fitVersion;
|
|
68
|
+
}
|
|
69
|
+
syncScroll();
|
|
70
|
+
};
|
|
71
|
+
measure();
|
|
72
|
+
let width = editor.clientWidth;
|
|
73
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
74
|
+
const observer = new ResizeObserver(() => {
|
|
75
|
+
if (editor.clientWidth === width) return;
|
|
76
|
+
width = editor.clientWidth;
|
|
77
|
+
measure();
|
|
78
|
+
});
|
|
79
|
+
observer.observe(editor);
|
|
80
|
+
return () => observer.disconnect();
|
|
81
|
+
}, [value, fitVersion]);
|
|
53
82
|
const selectQuery = (event) => {
|
|
54
83
|
if (event.detail < 3) return;
|
|
55
84
|
event.preventDefault();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"power-log-sql-editor.js","names":[],"sources":["../../src/renderer/power-log-sql-editor.tsx"],"sourcesContent":["import { useLayoutEffect, useMemo, useRef } from \"react\";\n\nimport type { MouseEvent } from \"react\";\n\ntype SqlToken = { text: string; kind?: \"keyword\" | \"function\" | \"string\" | \"identifier\" | \"number\" | \"comment\" };\nconst keywords = new Set(\n \"SELECT FROM WHERE AS AND OR NOT NULL IS IN LIKE GLOB BETWEEN EXISTS CASE WHEN THEN ELSE END DISTINCT ALL JOIN LEFT RIGHT INNER OUTER CROSS FULL ON USING GROUP BY HAVING ORDER ASC DESC LIMIT OFFSET UNION INTERSECT EXCEPT WITH RECURSIVE OVER PARTITION ROWS RANGE UNBOUNDED PRECEDING FOLLOWING CURRENT ROW NULLS FIRST LAST TRUE FALSE COLLATE CAST FILTER WINDOW VALUES EXPLAIN QUERY PLAN\".split(\n \" \",\n ),\n);\nconst lexeme =\n /--[^\\n]*(?:\\n|$)|\\/\\*[\\s\\S]*?(?:\\*\\/|$)|'(?:''|[^'])*(?:'|$)|\"(?:\"\"|[^\"])*(?:\"|$)|`(?:``|[^`])*(?:`|$)|\\[[^\\]]*(?:\\]|$)|\\b(?:0x[\\da-f]+|\\d+(?:\\.\\d*)?(?:e[+-]?\\d+)?)(?![\\w])|\\b[a-z_]\\w*\\b/gi;\n\nfunction isFunction(source: string, offset: number): boolean {\n while (offset < source.length && /\\s/.test(source[offset])) offset++;\n return source[offset] === \"(\";\n}\n\nexport function tokenizeSql(value: string): SqlToken[] {\n const source = value.slice(0, 65536);\n const tokens: SqlToken[] = [];\n let offset = 0;\n lexeme.lastIndex = 0;\n for (let match = lexeme.exec(source); match && tokens.length < 9998; match = lexeme.exec(source)) {\n if (match.index > offset) tokens.push({ text: source.slice(offset, match.index) });\n const text = match[0];\n const kind =\n text.startsWith(\"--\") || text.startsWith(\"/*\")\n ? \"comment\"\n : text.startsWith(\"'\")\n ? \"string\"\n : text.startsWith('\"') || text.startsWith(\"`\") || text.startsWith(\"[\")\n ? \"identifier\"\n : /^\\d/.test(text)\n ? \"number\"\n : keywords.has(text.toUpperCase())\n ? \"keyword\"\n : isFunction(source, match.index + text.length)\n ? \"function\"\n : undefined;\n tokens.push({ text, kind });\n offset = match.index + text.length;\n }\n if (offset < value.length) tokens.push({ text: value.slice(offset) });\n return tokens;\n}\n\nconst styles = `\n.power-logs .power-logs-sql-editor{position:relative;box-sizing:border-box;width:100%;height:56px;min-height:48px;max-height:max
|
|
1
|
+
{"version":3,"file":"power-log-sql-editor.js","names":[],"sources":["../../src/renderer/power-log-sql-editor.tsx"],"sourcesContent":["import { useLayoutEffect, useMemo, useRef } from \"react\";\n\nimport type { MouseEvent } from \"react\";\n\ntype SqlToken = { text: string; kind?: \"keyword\" | \"function\" | \"string\" | \"identifier\" | \"number\" | \"comment\" };\nconst keywords = new Set(\n \"SELECT FROM WHERE AS AND OR NOT NULL IS IN LIKE GLOB BETWEEN EXISTS CASE WHEN THEN ELSE END DISTINCT ALL JOIN LEFT RIGHT INNER OUTER CROSS FULL ON USING GROUP BY HAVING ORDER ASC DESC LIMIT OFFSET UNION INTERSECT EXCEPT WITH RECURSIVE OVER PARTITION ROWS RANGE UNBOUNDED PRECEDING FOLLOWING CURRENT ROW NULLS FIRST LAST TRUE FALSE COLLATE CAST FILTER WINDOW VALUES EXPLAIN QUERY PLAN\".split(\n \" \",\n ),\n);\nconst lexeme =\n /--[^\\n]*(?:\\n|$)|\\/\\*[\\s\\S]*?(?:\\*\\/|$)|'(?:''|[^'])*(?:'|$)|\"(?:\"\"|[^\"])*(?:\"|$)|`(?:``|[^`])*(?:`|$)|\\[[^\\]]*(?:\\]|$)|\\b(?:0x[\\da-f]+|\\d+(?:\\.\\d*)?(?:e[+-]?\\d+)?)(?![\\w])|\\b[a-z_]\\w*\\b/gi;\n\nfunction isFunction(source: string, offset: number): boolean {\n while (offset < source.length && /\\s/.test(source[offset])) offset++;\n return source[offset] === \"(\";\n}\n\nexport function tokenizeSql(value: string): SqlToken[] {\n const source = value.slice(0, 65536);\n const tokens: SqlToken[] = [];\n let offset = 0;\n lexeme.lastIndex = 0;\n for (let match = lexeme.exec(source); match && tokens.length < 9998; match = lexeme.exec(source)) {\n if (match.index > offset) tokens.push({ text: source.slice(offset, match.index) });\n const text = match[0];\n const kind =\n text.startsWith(\"--\") || text.startsWith(\"/*\")\n ? \"comment\"\n : text.startsWith(\"'\")\n ? \"string\"\n : text.startsWith('\"') || text.startsWith(\"`\") || text.startsWith(\"[\")\n ? \"identifier\"\n : /^\\d/.test(text)\n ? \"number\"\n : keywords.has(text.toUpperCase())\n ? \"keyword\"\n : isFunction(source, match.index + text.length)\n ? \"function\"\n : undefined;\n tokens.push({ text, kind });\n offset = match.index + text.length;\n }\n if (offset < value.length) tokens.push({ text: value.slice(offset) });\n return tokens;\n}\n\nconst styles = `\n.power-logs .power-logs-sql-editor{position:relative;box-sizing:border-box;width:100%;height:56px;min-height:48px;max-height:var(--sql-content-max-height,120px);flex-shrink:0;resize:vertical;overflow:hidden;border:1px solid var(--borderColor);border-radius:4px;background:var(--inputControlBackground,var(--contentColor));--sql-string:#e6a28c;--sql-number:#98c78e;--sql-function:#81b9e6;--sql-identifier:var(--textColorPrimary)}\n.power-logs .power-logs-sql-editor::-webkit-resizer{border:0;background:linear-gradient(135deg,transparent 45%,var(--borderColor) 46% 53%,transparent 54% 70%,var(--borderColor) 71% 78%,transparent 79%) center/10px 10px no-repeat}\n.theme-light .power-logs-sql-editor{--sql-string:#9e2b1a;--sql-number:#17642d;--sql-function:#005a9e;--sql-identifier:#684c9b}\n.power-logs .power-logs-sql-editor>textarea,.power-logs .power-logs-sql-editor>pre{position:absolute;inset:0;box-sizing:border-box;width:100%;height:100%;min-height:0;max-height:none;margin:0;padding:4px 8px;border:0;border-radius:0;font:12px/1.6 var(--font-monospace,monospace);letter-spacing:normal;white-space:pre-wrap;overflow-wrap:anywhere;tab-size:2;overflow:auto;scrollbar-gutter:stable;resize:none}\n.power-logs .power-logs-sql-editor>pre{pointer-events:none;color:var(--textColorPrimary);background:transparent;user-select:none}\n.power-logs .power-logs-sql-editor>textarea{color:transparent;background:transparent;caret-color:var(--textColorPrimary);-webkit-text-fill-color:transparent}\n.power-logs .power-logs-sql-editor>textarea::selection{background:rgba(100,150,240,.35);color:transparent}\n.power-logs-sql-editor [data-sql-token=keyword]{color:var(--primary)}\n.power-logs-sql-editor [data-sql-token=function]{color:var(--sql-function)}\n.power-logs-sql-editor [data-sql-token=string]{color:var(--sql-string)}\n.power-logs-sql-editor [data-sql-token=identifier]{color:var(--sql-identifier)}\n.power-logs-sql-editor [data-sql-token=number]{color:var(--sql-number)}\n.power-logs-sql-editor [data-sql-token=comment]{color:var(--textColorSecondary)}\n`;\n\nexport function SqlEditor({\n id,\n value,\n onChange,\n fitVersion = 0,\n}: {\n id: string;\n value: string;\n onChange(value: string): void;\n fitVersion?: number;\n}) {\n const fitted = useRef(0);\n const textarea = useRef<HTMLTextAreaElement>(null);\n const highlight = useRef<HTMLPreElement>(null);\n const tokens = useMemo(() => tokenizeSql(value), [value]);\n const syncScroll = () => {\n if (!textarea.current || !highlight.current) return;\n highlight.current.scrollTop = textarea.current.scrollTop;\n highlight.current.scrollLeft = textarea.current.scrollLeft;\n };\n useLayoutEffect(syncScroll, [value]);\n useLayoutEffect(() => {\n const pre = highlight.current;\n const editor = pre?.parentElement;\n if (!pre || !editor) return;\n const measure = () => {\n pre.style.height = \"auto\";\n pre.style.bottom = \"auto\";\n const height = pre.getBoundingClientRect().height;\n pre.style.removeProperty(\"height\");\n pre.style.removeProperty(\"bottom\");\n editor.style.setProperty(\"--sql-content-max-height\", `${Math.max(120, Math.min(240, Math.ceil(height) + 10))}px`);\n if (fitVersion !== fitted.current) {\n editor.style.height = `${Math.max(48, Math.min(240, Math.ceil(height) + 2))}px`;\n fitted.current = fitVersion;\n }\n syncScroll();\n };\n measure();\n let width = editor.clientWidth;\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (editor.clientWidth === width) return;\n width = editor.clientWidth;\n measure();\n });\n observer.observe(editor);\n return () => observer.disconnect();\n }, [value, fitVersion]);\n const selectQuery = (event: MouseEvent<HTMLTextAreaElement>) => {\n if (event.detail < 3) return;\n event.preventDefault();\n event.stopPropagation();\n window.getSelection()?.removeAllRanges();\n event.currentTarget.focus();\n event.currentTarget.select();\n };\n return (\n <div className=\"power-logs-sql-editor\">\n <style>{styles}</style>\n <pre ref={highlight} aria-hidden=\"true\">\n {tokens.map((token, index) => (\n <span key={index} data-sql-token={token.kind}>\n {token.text}\n </span>\n ))}\n {value.endsWith(\"\\n\") && \" \"}\n </pre>\n <textarea\n ref={textarea}\n id={id}\n value={value}\n maxLength={65536}\n spellCheck={false}\n onChange={(event) => onChange(event.target.value.slice(0, 65536))}\n onScroll={syncScroll}\n onMouseDown={selectQuery}\n onClick={selectQuery}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ function createPowerLogsClient(partition) {
|
|
|
8
8
|
...fields
|
|
9
9
|
});
|
|
10
10
|
return {
|
|
11
|
+
clearPersistent: () => invoke("clear-persistent"),
|
|
11
12
|
list: () => invoke("list"),
|
|
12
13
|
create: (target) => invoke("create", { target }),
|
|
13
14
|
append: (captureId, records) => invoke("append", {
|
|
@@ -20,6 +21,10 @@ function createPowerLogsClient(partition) {
|
|
|
20
21
|
notes
|
|
21
22
|
}),
|
|
22
23
|
delete: (captureId) => invoke("delete", { captureId }),
|
|
24
|
+
setPersistent: (captureId, persistent) => invoke("set-persistent", {
|
|
25
|
+
captureId,
|
|
26
|
+
persistent
|
|
27
|
+
}),
|
|
23
28
|
saveSql: (captureId, sql) => invoke("save-sql", {
|
|
24
29
|
captureId,
|
|
25
30
|
sql
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"power-logs-client.js","names":[],"sources":["../../src/renderer/power-logs-client.ts"],"sourcesContent":["import { ipcRenderer } from \"electron\";\nimport {\n type LogCapture,\n type LogPartition,\n type LogQueryResult,\n type LogRecord,\n type LogTarget,\n POWER_LOGS_CHANNEL,\n} from \"../common/power-logs\";\n\nexport function createPowerLogsClient(partition: LogPartition) {\n const invoke = <T>(operation: string, fields: object = {}): Promise<T> =>\n ipcRenderer.invoke(POWER_LOGS_CHANNEL, { ...partition, operation, ...fields });\n return {\n list: () => invoke<LogCapture[]>(\"list\"),\n create: (target: LogTarget) => invoke<LogCapture>(\"create\", { target }),\n append: (captureId: string, records: LogRecord[]) => invoke<LogCapture>(\"append\", { captureId, records }),\n finish: (captureId: string, partial: boolean, notes: string[]) =>\n invoke<LogCapture>(\"finish\", { captureId, partial, notes }),\n delete: (captureId: string) => invoke<boolean>(\"delete\", { captureId }),\n saveSql: (captureId: string, sql: string) => invoke<LogCapture>(\"save-sql\", { captureId, sql }),\n query: (captureId: string, queryId: string, sql: string) =>\n invoke<LogQueryResult>(\"query\", { captureId, queryId, sql }),\n cancel: (queryId: string) => invoke<boolean>(\"cancel\", { queryId }),\n export: (captureId: string) => invoke<boolean>(\"export\", { captureId }),\n };\n}\n"],"mappings":";;;AAUA,SAAgB,sBAAsB,WAAyB;CAC7D,MAAM,UAAa,WAAmB,SAAiB,CAAC,MACtD,SAAA,YAAY,OAAO,mBAAA,oBAAoB;EAAE,GAAG;EAAW;EAAW,GAAG;CAAO,CAAC;CAC/E,OAAO;EACL,YAAY,OAAqB,MAAM;EACvC,SAAS,WAAsB,OAAmB,UAAU,EAAE,OAAO,CAAC;EACtE,SAAS,WAAmB,YAAyB,OAAmB,UAAU;GAAE;GAAW;EAAQ,CAAC;EACxG,SAAS,WAAmB,SAAkB,UAC5C,OAAmB,UAAU;GAAE;GAAW;GAAS;EAAM,CAAC;EAC5D,SAAS,cAAsB,OAAgB,UAAU,EAAE,UAAU,CAAC;EACtE,UAAU,WAAmB,QAAgB,OAAmB,YAAY;GAAE;GAAW;EAAI,CAAC;EAC9F,QAAQ,WAAmB,SAAiB,QAC1C,OAAuB,SAAS;GAAE;GAAW;GAAS;EAAI,CAAC;EAC7D,SAAS,YAAoB,OAAgB,UAAU,EAAE,QAAQ,CAAC;EAClE,SAAS,cAAsB,OAAgB,UAAU,EAAE,UAAU,CAAC;CACxE;AACF"}
|
|
1
|
+
{"version":3,"file":"power-logs-client.js","names":[],"sources":["../../src/renderer/power-logs-client.ts"],"sourcesContent":["import { ipcRenderer } from \"electron\";\nimport {\n type LogCapture,\n type LogPartition,\n type LogQueryResult,\n type LogRecord,\n type LogTarget,\n POWER_LOGS_CHANNEL,\n} from \"../common/power-logs\";\n\nexport function createPowerLogsClient(partition: LogPartition) {\n const invoke = <T>(operation: string, fields: object = {}): Promise<T> =>\n ipcRenderer.invoke(POWER_LOGS_CHANNEL, { ...partition, operation, ...fields });\n return {\n clearPersistent: () => invoke<boolean>(\"clear-persistent\"),\n list: () => invoke<LogCapture[]>(\"list\"),\n create: (target: LogTarget) => invoke<LogCapture>(\"create\", { target }),\n append: (captureId: string, records: LogRecord[]) => invoke<LogCapture>(\"append\", { captureId, records }),\n finish: (captureId: string, partial: boolean, notes: string[]) =>\n invoke<LogCapture>(\"finish\", { captureId, partial, notes }),\n delete: (captureId: string) => invoke<boolean>(\"delete\", { captureId }),\n setPersistent: (captureId: string, persistent: boolean) =>\n invoke<LogCapture>(\"set-persistent\", { captureId, persistent }),\n saveSql: (captureId: string, sql: string) => invoke<LogCapture>(\"save-sql\", { captureId, sql }),\n query: (captureId: string, queryId: string, sql: string) =>\n invoke<LogQueryResult>(\"query\", { captureId, queryId, sql }),\n cancel: (queryId: string) => invoke<boolean>(\"cancel\", { queryId }),\n export: (captureId: string) => invoke<boolean>(\"export\", { captureId }),\n };\n}\n"],"mappings":";;;AAUA,SAAgB,sBAAsB,WAAyB;CAC7D,MAAM,UAAa,WAAmB,SAAiB,CAAC,MACtD,SAAA,YAAY,OAAO,mBAAA,oBAAoB;EAAE,GAAG;EAAW;EAAW,GAAG;CAAO,CAAC;CAC/E,OAAO;EACL,uBAAuB,OAAgB,kBAAkB;EACzD,YAAY,OAAqB,MAAM;EACvC,SAAS,WAAsB,OAAmB,UAAU,EAAE,OAAO,CAAC;EACtE,SAAS,WAAmB,YAAyB,OAAmB,UAAU;GAAE;GAAW;EAAQ,CAAC;EACxG,SAAS,WAAmB,SAAkB,UAC5C,OAAmB,UAAU;GAAE;GAAW;GAAS;EAAM,CAAC;EAC5D,SAAS,cAAsB,OAAgB,UAAU,EAAE,UAAU,CAAC;EACtE,gBAAgB,WAAmB,eACjC,OAAmB,kBAAkB;GAAE;GAAW;EAAW,CAAC;EAChE,UAAU,WAAmB,QAAgB,OAAmB,YAAY;GAAE;GAAW;EAAI,CAAC;EAC9F,QAAQ,WAAmB,SAAiB,QAC1C,OAAuB,SAAS;GAAE;GAAW;GAAS;EAAI,CAAC;EAC7D,SAAS,YAAoB,OAAgB,UAAU,EAAE,QAAQ,CAAC;EAClE,SAAS,cAAsB,OAAgB,UAAU,EAAE,UAAU,CAAC;CACxE;AACF"}
|