@litelens/core 1.7.1 → 1.7.3
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 +66 -2
- package/dist/index.d.ts +159 -26
- package/dist/index.js +53 -4
- package/dist/tsup-preset.d.ts +33 -0
- package/dist/tsup-preset.js +99 -0
- package/package.json +14 -5
package/README.md
CHANGED
|
@@ -18,8 +18,72 @@ So this package exists to give plugin authors real types, JSDoc, and editor auto
|
|
|
18
18
|
|
|
19
19
|
## Contents
|
|
20
20
|
|
|
21
|
-
- **`src/
|
|
22
|
-
- **`src/
|
|
21
|
+
- **`src/clusterWideAPI.ts`** (exported as `clusterWideAPI`) — capabilities scoped to the single-cluster view. See "Using `clusterWideAPI`" below.
|
|
22
|
+
- **`src/appWideAPI.ts`** (exported as `appWideAPI`) — capabilities with no single-cluster-view constraint. See "Using `appWideAPI`" below.
|
|
23
|
+
- **`src/types/`** — shared TypeScript types re-exported alongside the API namespaces above (`api`, `nav`, `resources`, `tray`).
|
|
24
|
+
- **`src/build/tsupPreset.ts`** (exported as `@litelens/core/tsup-preset`) — shared tsup build config for plugin frontends: Node-only build tooling, kept out of the `.` export above so it never ships in the browser bundle the vendor shim substitutes for. See "Shared plugin build config" below.
|
|
25
|
+
|
|
26
|
+
## Using `clusterWideAPI`
|
|
27
|
+
|
|
28
|
+
Everything under `clusterWideAPI` is only valid inside the single-cluster view (i.e. a component rendered within `MainLayout`'s subtree). Calling the hooks from an app-wide screen (Settings, Marketplace) throws.
|
|
29
|
+
|
|
30
|
+
- **`useExposeProperties()`** — hook returning cluster-scoped state: `activeContext`, `activeNamespaces`, `activeResource`, `availableNamespaces`, `resourceLinks` (open a built-in resource's detail drawer, e.g. `resourceLinks.pod(namespace, name)`), and `unifiedTray` (`{ openTab }` for the bottom tray).
|
|
31
|
+
- **`useExposeMethods()`** — hook returning cluster-scoped actions, currently `onNavigateToView(view)`.
|
|
32
|
+
- **`registerViews(pluginId, configs)`** — registers your plugin's main view component(s), one per resource you own. Each `config.name` must match the `view` value used in the nav entry you register via `registerNavEntry` — the host mounts whichever registered view's `name` equals the currently active resource. Optionally pass a per-view `stylesheet` (a `Promise` from a CSS import) that loads only when that view mounts.
|
|
33
|
+
- **`registerNavEntry(pluginId, navEntry)`** — registers your plugin's sidebar entry (a single item or a group of items, see `NavEntry` in `src/types/nav.ts`).
|
|
34
|
+
- **`registerTrayFamilies(pluginId, families)`** — registers content components for tray families your plugin owns, keyed by an arbitrary family name your own `openTab` calls reference.
|
|
35
|
+
- **`registerEvents(pluginId, handlers)`** — subscribes your plugin to the host's plugin event bus, keyed by event name.
|
|
36
|
+
|
|
37
|
+
`registerViews`, `registerNavEntry`, `registerTrayFamilies`, and `registerEvents` are typically all called once, at module scope, in your plugin's entry file — that way your view, nav entry, tray content, and event handlers are all available as soon as the host dynamically imports your bundle, with no component needing to mount first. Re-registering under the same `pluginId` replaces the previous registration; the host also unregisters everything automatically when the plugin is uninstalled.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { clusterWideAPI } from "@litelens/core";
|
|
41
|
+
import { HelmChartListView } from "./views/HelmChartListView";
|
|
42
|
+
import { HELM_NAV_ENTRY } from "./nav";
|
|
43
|
+
import { HELM_TRAY_FAMILIES } from "./tray";
|
|
44
|
+
|
|
45
|
+
const PLUGIN_ID = "helm";
|
|
46
|
+
|
|
47
|
+
clusterWideAPI.registerViews(PLUGIN_ID, [{ name: "helm-charts", component: HelmChartListView }]);
|
|
48
|
+
clusterWideAPI.registerNavEntry(PLUGIN_ID, HELM_NAV_ENTRY);
|
|
49
|
+
clusterWideAPI.registerTrayFamilies(PLUGIN_ID, HELM_TRAY_FAMILIES);
|
|
50
|
+
clusterWideAPI.registerEvents(PLUGIN_ID, {
|
|
51
|
+
"helm:release-updated": (payload) => {
|
|
52
|
+
appWideAPI.getQueryClient().invalidateQueries({ queryKey: ["helm", "releases"] });
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Inside a mounted view component:
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
function HelmChartListView() {
|
|
61
|
+
const { activeContext, resourceLinks } = clusterWideAPI.useExposeProperties();
|
|
62
|
+
const { onNavigateToView } = clusterWideAPI.useExposeMethods();
|
|
63
|
+
// ...
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Using `appWideAPI`
|
|
68
|
+
|
|
69
|
+
- **`registerStylesheets(pluginId, stylesheets)`** — registers your plugin's global stylesheet(s) (e.g. compiled Tailwind output), loaded once at the app level regardless of which of your views is active. Call this once at module scope, alongside the `clusterWideAPI` registration calls above — don't use per-view `stylesheet` on `registerViews` for CSS that should apply across all of your views.
|
|
70
|
+
- **`getQueryClient()`** — returns the host's singleton `QueryClient`. Use this from code that isn't a mounted React component (e.g. the module-scope `registerEvents` handler above) and therefore can't call `useQueryClient()`.
|
|
71
|
+
|
|
72
|
+
## Shared plugin build config
|
|
73
|
+
|
|
74
|
+
`@litelens/core/tsup-preset` exports `createPluginTsupConfig({ pluginRoot })`, the tsup config every plugin frontend needs: externalizes the host-shared runtime deps (`PLUGIN_SHARED_EXTERNALS`), inlines Tailwind-compiled CSS as text via a local Tailwind CLI pass, and optionally emits a bundle-analysis report to `dist/stats/` when `ANALYZE=true`. A plugin's own `tsup.config.ts` becomes:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { createPluginTsupConfig } from "@litelens/core/tsup-preset";
|
|
78
|
+
import path from "node:path";
|
|
79
|
+
import { fileURLToPath } from "node:url";
|
|
80
|
+
|
|
81
|
+
export default createPluginTsupConfig({
|
|
82
|
+
pluginRoot: path.dirname(fileURLToPath(import.meta.url)),
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Pass `entry` or `external` to override the entrypoint or add plugin-specific externals. Unlike the `.` export, this subpath pulls in real Node dependencies (`tsup`, `esbuild-visualizer`, `@tailwindcss/cli`) — they're declared as `dependencies` of this package (not `devDependencies`) so consuming plugins get them transitively.
|
|
23
87
|
|
|
24
88
|
## Versioning
|
|
25
89
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ElementType, ReactNode, ComponentType } from 'react';
|
|
2
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
2
3
|
|
|
3
4
|
interface UseQueryCallback<T = unknown> {
|
|
4
5
|
select?: (data?: T) => T;
|
|
@@ -905,50 +906,182 @@ interface SharedUnifiedTrayContext {
|
|
|
905
906
|
}
|
|
906
907
|
|
|
907
908
|
/**
|
|
908
|
-
*
|
|
909
|
-
*
|
|
910
|
-
*
|
|
911
|
-
*
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
*
|
|
915
|
-
* of capabilities valid only within the single-cluster view — i.e. inside
|
|
916
|
-
* MainLayout's subtree (MainLayoutProvider → DetailDrawerProvider). Calling
|
|
917
|
-
* this from a component rendered outside that subtree (e.g. Settings,
|
|
918
|
-
* Marketplace, or any future app-wide screen) will throw, because the
|
|
919
|
-
* underlying host state (DetailDrawerContext) has no provider there. A future
|
|
920
|
-
* useAppWideAPI() will cover capabilities that don't have this constraint.
|
|
909
|
+
* Hook to access cluster-scoped property values exposed to plugins. Valid
|
|
910
|
+
* only within the single-cluster view — i.e. inside MainLayout's subtree
|
|
911
|
+
* (MainLayoutProvider → DetailDrawerProvider). Calling this from a component
|
|
912
|
+
* rendered outside that subtree (e.g. Settings, Marketplace, or any future
|
|
913
|
+
* app-wide screen) will throw, because the underlying host state
|
|
914
|
+
* (DetailDrawerContext) has no provider there. A future appWideAPI will
|
|
915
|
+
* cover capabilities that don't have this constraint.
|
|
921
916
|
*
|
|
922
917
|
* Example:
|
|
923
|
-
* const { activeContext, activeNamespaces, activeResource, availableNamespaces,
|
|
918
|
+
* const { activeContext, activeNamespaces, activeResource, availableNamespaces, resourceLinks, unifiedTray } = clusterWideAPI.useExposeProperties();
|
|
924
919
|
* resourceLinks.pod(namespace, podName); // Opens pod detail drawer
|
|
925
920
|
* unifiedTray.openTab("my-plugin-family", { pluginId: "my-plugin", label: "...", dedupeKey: "..." });
|
|
926
|
-
* useRegisterClusterWideEvents({
|
|
927
|
-
* "helm:release-updated": (payload) => { console.log("Release updated:", payload); },
|
|
928
|
-
* });
|
|
929
|
-
* useRegisterNavEntry("helm", "Helm", HELM_NAV_ENTRY);
|
|
930
|
-
* useRegisterTrayFamilies("helm", HELM_TRAY_FAMILIES);
|
|
931
921
|
*
|
|
932
922
|
* This signature is duplicated from the host's real implementation at
|
|
933
|
-
* frontend/src/expose/hooks/
|
|
923
|
+
* frontend/src/expose/hooks/useExposeProperties.ts (which this package can't
|
|
934
924
|
* import directly — see main.tsx's vendor injection). If that hook's return
|
|
935
925
|
* type changes, update this signature to match.
|
|
936
926
|
*/
|
|
937
|
-
declare function
|
|
927
|
+
declare function useExposeProperties(): {
|
|
938
928
|
activeContext: string;
|
|
939
929
|
activeNamespaces: string[];
|
|
940
930
|
activeResource: string;
|
|
941
931
|
availableNamespaces: Array<{
|
|
942
932
|
Name: string;
|
|
943
933
|
}>;
|
|
944
|
-
onNavigateToView: (view: string) => void;
|
|
945
934
|
resourceLinks: Record<string, (namespace: string, name: string) => void>;
|
|
946
935
|
unifiedTray: {
|
|
947
936
|
openTab: (family: string, params: unknown) => void;
|
|
948
937
|
} | null;
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
938
|
+
};
|
|
939
|
+
/**
|
|
940
|
+
* Hook to access cluster-scoped plain functions exposed to plugins. Valid
|
|
941
|
+
* only within the single-cluster view — same constraints as useExposeProperties().
|
|
942
|
+
*
|
|
943
|
+
* Example:
|
|
944
|
+
* const { onNavigateToView } = clusterWideAPI.useExposeMethods();
|
|
945
|
+
*
|
|
946
|
+
* This signature is duplicated from the host's real implementation at
|
|
947
|
+
* frontend/src/expose/hooks/useExposeMethods.ts (which this package can't
|
|
948
|
+
* import directly — see main.tsx's vendor injection). If that hook's return
|
|
949
|
+
* type changes, update this signature to match.
|
|
950
|
+
*/
|
|
951
|
+
declare function useExposeMethods(): {
|
|
952
|
+
onNavigateToView: (view: string) => void;
|
|
953
|
+
};
|
|
954
|
+
/**
|
|
955
|
+
* Register this plugin's event handlers with the host's plugin event bus.
|
|
956
|
+
* Called once by a plugin, typically at module scope alongside
|
|
957
|
+
* registerViews/registerNavEntry/registerTrayFamilies. Re-registering under
|
|
958
|
+
* the same plugin ID replaces its handlers; the host also unregisters them
|
|
959
|
+
* automatically when the plugin is uninstalled.
|
|
960
|
+
*
|
|
961
|
+
* Example:
|
|
962
|
+
* const queryClient = appWideAPI.getQueryClient();
|
|
963
|
+
* clusterWideAPI.registerEvents("helm", {
|
|
964
|
+
* "helm:release-updated": (payload) => { queryClient.invalidateQueries(...); },
|
|
965
|
+
* });
|
|
966
|
+
*
|
|
967
|
+
* This function is replaced at runtime by the host's actual implementation
|
|
968
|
+
* (injected in frontend/src/expose/index.tsx). If you see this error, registerEvents
|
|
969
|
+
* was called before the host initialized the injection.
|
|
970
|
+
*/
|
|
971
|
+
declare function registerEvents(pluginId: string, handlers: Record<string, (payload: any) => void>): void;
|
|
972
|
+
/**
|
|
973
|
+
* Register this plugin's tray-family content components with the host's
|
|
974
|
+
* unified bottom tray. Called once by a plugin, typically at module scope
|
|
975
|
+
* alongside registerViews/registerNavEntry, so the plugin's tray content is
|
|
976
|
+
* available as soon as the plugin's bundle is imported — no component needs
|
|
977
|
+
* to mount first.
|
|
978
|
+
*
|
|
979
|
+
* Example:
|
|
980
|
+
* clusterWideAPI.registerTrayFamilies("helm", HELM_TRAY_FAMILIES);
|
|
981
|
+
*
|
|
982
|
+
* This function is replaced at runtime by the host's actual implementation
|
|
983
|
+
* (injected in frontend/src/expose/index.tsx). If you see this error, registerTrayFamilies
|
|
984
|
+
* was called before the host initialized the injection.
|
|
985
|
+
*/
|
|
986
|
+
declare function registerTrayFamilies(pluginId: string, families: Record<string, ComponentType<SharedUnifiedTrayContentProps>> | undefined): void;
|
|
987
|
+
/**
|
|
988
|
+
* Register one or more named view components with the host. Called by
|
|
989
|
+
* plugins to provide their main view UI, one per resource the plugin owns.
|
|
990
|
+
* `name` must match the resource's nav entry `view` value (see
|
|
991
|
+
* registerNavEntry) — the host mounts whichever registered view's `name`
|
|
992
|
+
* equals the currently active resource and keeps the rest hidden, so a
|
|
993
|
+
* plugin no longer needs to switch on the active resource itself. Each view
|
|
994
|
+
* may optionally supply its own `stylesheet`, loaded only when that view
|
|
995
|
+
* mounts — for a plugin's global stylesheet (e.g. Tailwind output shared
|
|
996
|
+
* across all its views), use appWideAPI.registerStylesheets instead, which
|
|
997
|
+
* loads once at the app level regardless of which view is active.
|
|
998
|
+
*
|
|
999
|
+
* Example:
|
|
1000
|
+
* clusterWideAPI.registerViews("helm", [
|
|
1001
|
+
* { name: "helm-charts", component: HelmChartListView, stylesheet: import("./chart-list.css") },
|
|
1002
|
+
* { name: "helm-releases", component: HelmReleaseListView },
|
|
1003
|
+
* ]);
|
|
1004
|
+
*
|
|
1005
|
+
* This function is replaced at runtime by the host's actual implementation
|
|
1006
|
+
* (injected in frontend/src/expose/index.tsx). If you see this error, registerViews
|
|
1007
|
+
* was called before the host initialized the injection.
|
|
1008
|
+
*/
|
|
1009
|
+
declare function registerViews(pluginId: string, configs: Array<{
|
|
1010
|
+
name: string;
|
|
1011
|
+
component: ComponentType;
|
|
1012
|
+
stylesheet?: Promise<{
|
|
1013
|
+
default: string;
|
|
1014
|
+
}>;
|
|
1015
|
+
}>): void;
|
|
1016
|
+
/**
|
|
1017
|
+
* Register this plugin's sidebar nav entry with the host. Called once by a
|
|
1018
|
+
* plugin, typically at module scope alongside registerViews, so the entry
|
|
1019
|
+
* appears in the sidebar as soon as the plugin's bundle is imported — no
|
|
1020
|
+
* component needs to mount first.
|
|
1021
|
+
*
|
|
1022
|
+
* Example:
|
|
1023
|
+
* clusterWideAPI.registerNavEntry("helm", HELM_NAV_ENTRY);
|
|
1024
|
+
*
|
|
1025
|
+
* This function is replaced at runtime by the host's actual implementation
|
|
1026
|
+
* (injected in frontend/src/expose/index.tsx). If you see this error, registerNavEntry
|
|
1027
|
+
* was called before the host initialized the injection.
|
|
1028
|
+
*/
|
|
1029
|
+
declare function registerNavEntry(pluginId: string, navEntry: NavEntry<string> | undefined): void;
|
|
1030
|
+
/**
|
|
1031
|
+
* Cluster-scoped capabilities exposed to plugins, valid only within the
|
|
1032
|
+
* single-cluster view (see useExposeProperties() for the exact constraint).
|
|
1033
|
+
* A future appWideAPI namespace will cover capabilities that don't have
|
|
1034
|
+
* this constraint.
|
|
1035
|
+
*
|
|
1036
|
+
* Example:
|
|
1037
|
+
* const { onNavigateToView } = clusterWideAPI.useExposeMethods();
|
|
1038
|
+
*/
|
|
1039
|
+
declare const clusterWideAPI: {
|
|
1040
|
+
useExposeProperties: typeof useExposeProperties;
|
|
1041
|
+
useExposeMethods: typeof useExposeMethods;
|
|
1042
|
+
registerViews: typeof registerViews;
|
|
1043
|
+
registerNavEntry: typeof registerNavEntry;
|
|
1044
|
+
registerTrayFamilies: typeof registerTrayFamilies;
|
|
1045
|
+
registerEvents: typeof registerEvents;
|
|
1046
|
+
};
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* Register the plugin's global stylesheet(s) with the host. Unlike
|
|
1050
|
+
* clusterWideAPI.registerViews, this isn't scoped per-view — a plugin's
|
|
1051
|
+
* compiled CSS (e.g. Tailwind output) applies across all of its views, so
|
|
1052
|
+
* it's registered once per plugin rather than attached to each view config.
|
|
1053
|
+
*
|
|
1054
|
+
* Example:
|
|
1055
|
+
* appWideAPI.registerStylesheets("helm", [import("./style.css")]);
|
|
1056
|
+
*
|
|
1057
|
+
* This function is replaced at runtime by the host's actual implementation
|
|
1058
|
+
* (injected in frontend/src/expose/index.tsx). If you see this error,
|
|
1059
|
+
* registerStylesheets was called before the host initialized the injection.
|
|
1060
|
+
*/
|
|
1061
|
+
declare function registerStylesheets(pluginId: string, stylesheets: Array<Promise<{
|
|
1062
|
+
default: string;
|
|
1063
|
+
}>>): void;
|
|
1064
|
+
/**
|
|
1065
|
+
* Get the host's singleton QueryClient instance. Useful for plugin code
|
|
1066
|
+
* that isn't a mounted React component (e.g. module-scope registration in
|
|
1067
|
+
* index.ts) and therefore can't call useQueryClient()'s hook.
|
|
1068
|
+
*
|
|
1069
|
+
* Example:
|
|
1070
|
+
* const queryClient = appWideAPI.getQueryClient();
|
|
1071
|
+
* queryClient.invalidateQueries({ queryKey: [...] });
|
|
1072
|
+
*
|
|
1073
|
+
* This function is replaced at runtime by the host's actual implementation
|
|
1074
|
+
* (injected in frontend/src/expose/index.tsx). If you see this error,
|
|
1075
|
+
* getQueryClient was called before the host initialized the injection.
|
|
1076
|
+
*/
|
|
1077
|
+
declare function getQueryClient(): QueryClient;
|
|
1078
|
+
/**
|
|
1079
|
+
* App-wide capabilities exposed to plugins — not scoped to the single-cluster
|
|
1080
|
+
* view, unlike clusterWideAPI (see useExposeProperties() for that constraint).
|
|
1081
|
+
*/
|
|
1082
|
+
declare const appWideAPI: {
|
|
1083
|
+
registerStylesheets: typeof registerStylesheets;
|
|
1084
|
+
getQueryClient: typeof getQueryClient;
|
|
952
1085
|
};
|
|
953
1086
|
|
|
954
|
-
export { type CRBSubject, type ClusterRole, type ClusterRoleBinding, type ConfigMap, type CronJob, type CronJobSummary, type DaemonSet, type DaemonSetSummary, type Deployment, type DeploymentCondition, type DeploymentSummary, type Endpoint, type EndpointAddress, type EndpointPort, type EndpointSlice, type EndpointSliceEndpoint, type EndpointSlicePort, type EndpointSubset, type Event, type HPA, type HPADetail, type HPAMetric, type Ingress, type IngressClass, type IngressDetail, type IngressPath, type IngressRule, type Job, type JobCondition, type JobSummary, type Lease, type LimitRange, type LimitRangeDetail, type ManagedField, type Namespace, type NavEntry, type NavGroup, type NavItem, type NetworkPolicy, type NetworkPolicyDetail, type NetworkPolicyEgressRule, type NetworkPolicyIngressRule, type NetworkPolicyPeer, type Node, type NodeAddress, type NodeCondition, type PersistentVolume, type PersistentVolumeClaim, type PersistentVolumeClaimDetail, type PersistentVolumeDetail, type Pod, type PodCondition, type PodContainerDetail, type PodContainerLastStatus, type PodContainerMount, type PodContainerPort, type PodDisruptionBudget, type PodDisruptionBudgetDetail, type PodSummary, type PodVolume, type PodVolumeSource, type PolicyRule, type PortForward, type PriorityClass, type RBSubject, type ReplicaSet, type ReplicaSetSummary, type ResourceQuota, type ResourceQuotaDetail, type Role, type RoleBinding, type ScaleTargetRef, type Secret, type SecretDetail, type Service, type ServiceAccount, type ServicePort, type SharedNamespaceContext, type SharedUnifiedTrayContentProps, type SharedUnifiedTrayContext, type SharedUnifiedTrayOpenParams, type SharedUnifiedTrayTab, type StatefulSet, type StatefulSetSummary, type StorageClass, type TolerationDetail, type UnifiedTrayAllFamily, type UnifiedTrayCoreFamily, type UseQueryCallback, type ValidatingWebhookConfig, type ValidatingWebhookConfigDetail, type WebhookDetail,
|
|
1087
|
+
export { type CRBSubject, type ClusterRole, type ClusterRoleBinding, type ConfigMap, type CronJob, type CronJobSummary, type DaemonSet, type DaemonSetSummary, type Deployment, type DeploymentCondition, type DeploymentSummary, type Endpoint, type EndpointAddress, type EndpointPort, type EndpointSlice, type EndpointSliceEndpoint, type EndpointSlicePort, type EndpointSubset, type Event, type HPA, type HPADetail, type HPAMetric, type Ingress, type IngressClass, type IngressDetail, type IngressPath, type IngressRule, type Job, type JobCondition, type JobSummary, type Lease, type LimitRange, type LimitRangeDetail, type ManagedField, type Namespace, type NavEntry, type NavGroup, type NavItem, type NetworkPolicy, type NetworkPolicyDetail, type NetworkPolicyEgressRule, type NetworkPolicyIngressRule, type NetworkPolicyPeer, type Node, type NodeAddress, type NodeCondition, type PersistentVolume, type PersistentVolumeClaim, type PersistentVolumeClaimDetail, type PersistentVolumeDetail, type Pod, type PodCondition, type PodContainerDetail, type PodContainerLastStatus, type PodContainerMount, type PodContainerPort, type PodDisruptionBudget, type PodDisruptionBudgetDetail, type PodSummary, type PodVolume, type PodVolumeSource, type PolicyRule, type PortForward, type PriorityClass, type RBSubject, type ReplicaSet, type ReplicaSetSummary, type ResourceQuota, type ResourceQuotaDetail, type Role, type RoleBinding, type ScaleTargetRef, type Secret, type SecretDetail, type Service, type ServiceAccount, type ServicePort, type SharedNamespaceContext, type SharedUnifiedTrayContentProps, type SharedUnifiedTrayContext, type SharedUnifiedTrayOpenParams, type SharedUnifiedTrayTab, type StatefulSet, type StatefulSetSummary, type StorageClass, type TolerationDetail, type UnifiedTrayAllFamily, type UnifiedTrayCoreFamily, type UseQueryCallback, type ValidatingWebhookConfig, type ValidatingWebhookConfigDetail, type WebhookDetail, appWideAPI, clusterWideAPI };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,57 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
function
|
|
1
|
+
// src/clusterWideAPI.ts
|
|
2
|
+
function useExposeProperties() {
|
|
3
3
|
throw new Error(
|
|
4
|
-
"
|
|
4
|
+
"clusterWideAPI.useExposeProperties is not available. This hook must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
5
5
|
);
|
|
6
6
|
}
|
|
7
|
+
function useExposeMethods() {
|
|
8
|
+
throw new Error(
|
|
9
|
+
"clusterWideAPI.useExposeMethods is not available. This hook must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
function registerEvents(pluginId, handlers) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
"clusterWideAPI.registerEvents is not available. This function must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
function registerTrayFamilies(pluginId, families) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
"clusterWideAPI.registerTrayFamilies is not available. This function must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
function registerViews(pluginId, configs) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
"clusterWideAPI.registerViews is not available. This function must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function registerNavEntry(pluginId, navEntry) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
"clusterWideAPI.registerNavEntry is not available. This function must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
var clusterWideAPI = {
|
|
33
|
+
useExposeProperties,
|
|
34
|
+
useExposeMethods,
|
|
35
|
+
registerViews,
|
|
36
|
+
registerNavEntry,
|
|
37
|
+
registerTrayFamilies,
|
|
38
|
+
registerEvents
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/appWideAPI.ts
|
|
42
|
+
function registerStylesheets(pluginId, stylesheets) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"appWideAPI.registerStylesheets is not available. This function must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function getQueryClient() {
|
|
48
|
+
throw new Error(
|
|
49
|
+
"appWideAPI.getQueryClient is not available. This function must be imported from '@litelens/core' within a plugin bundle loaded by the litelens host."
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
var appWideAPI = {
|
|
53
|
+
registerStylesheets,
|
|
54
|
+
getQueryClient
|
|
55
|
+
};
|
|
7
56
|
|
|
8
|
-
export {
|
|
57
|
+
export { appWideAPI, clusterWideAPI };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Options } from 'tsup';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Externals every plugin frontend must share with the host's own module
|
|
5
|
+
* instances (resolved via the host's import map + vendor shims) rather than
|
|
6
|
+
* bundling its own copy — required for react-dom/@tanstack/react-query
|
|
7
|
+
* context objects to resolve correctly when a plugin component is mounted
|
|
8
|
+
* inline in the host's fiber tree.
|
|
9
|
+
*/
|
|
10
|
+
declare const PLUGIN_SHARED_EXTERNALS: readonly ["react", "react-dom", "@litelens/design-system", "@tanstack/react-query", "@litelens/core"];
|
|
11
|
+
interface CreatePluginTsupConfigOptions {
|
|
12
|
+
/** Absolute path to the plugin frontend package's root directory (e.g.
|
|
13
|
+
* `path.dirname(fileURLToPath(import.meta.url))` from the plugin's own
|
|
14
|
+
* `tsup.config.ts`). Used as the Tailwind CLI's `--cwd` and to resolve the
|
|
15
|
+
* package name for the bundle-report title. */
|
|
16
|
+
pluginRoot: string;
|
|
17
|
+
/** Defaults to `["src/index.ts"]`. */
|
|
18
|
+
entry?: string[];
|
|
19
|
+
/** Extra externals beyond {@link PLUGIN_SHARED_EXTERNALS}. */
|
|
20
|
+
external?: string[];
|
|
21
|
+
/** Defaults to `process.env.ANALYZE === "true"`. */
|
|
22
|
+
analyze?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Shared tsup config for litelens plugin frontends: bundles `src/index.ts`
|
|
26
|
+
* to a single ESM file, externalizing the host-shared runtime deps, inlining
|
|
27
|
+
* Tailwind-compiled CSS as text (see {@link createInlineTailwindPlugin}), and
|
|
28
|
+
* optionally emitting a bundle-analysis report to `dist/stats/` when
|
|
29
|
+
* `ANALYZE=true`.
|
|
30
|
+
*/
|
|
31
|
+
declare function createPluginTsupConfig(options: CreatePluginTsupConfigOptions): Options;
|
|
32
|
+
|
|
33
|
+
export { type CreatePluginTsupConfigOptions, PLUGIN_SHARED_EXTERNALS, createPluginTsupConfig };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { visualizer, prepareVisualizerData } from 'esbuild-visualizer';
|
|
2
|
+
import { execFileSync } from 'child_process';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
// src/build/tsupPreset.ts
|
|
8
|
+
var PLUGIN_SHARED_EXTERNALS = [
|
|
9
|
+
"react",
|
|
10
|
+
"react-dom",
|
|
11
|
+
"@litelens/design-system",
|
|
12
|
+
"@tanstack/react-query",
|
|
13
|
+
"@litelens/core"
|
|
14
|
+
];
|
|
15
|
+
var require2 = createRequire(import.meta.url);
|
|
16
|
+
function resolveTailwindCliEntry() {
|
|
17
|
+
const tailwindCliPkg = JSON.parse(
|
|
18
|
+
fs.readFileSync(require2.resolve("@tailwindcss/cli/package.json"), "utf-8")
|
|
19
|
+
);
|
|
20
|
+
return path.join(
|
|
21
|
+
path.dirname(require2.resolve("@tailwindcss/cli/package.json")),
|
|
22
|
+
tailwindCliPkg.bin.tailwindcss
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
var RESOLVED_SUFFIX = ".tw-inline";
|
|
26
|
+
function createInlineTailwindPlugin(pluginRoot) {
|
|
27
|
+
const tailwindCliEntry = resolveTailwindCliEntry();
|
|
28
|
+
return {
|
|
29
|
+
name: "inline-tailwind",
|
|
30
|
+
setup(build) {
|
|
31
|
+
build.onResolve({ filter: /\.css$/ }, (args) => {
|
|
32
|
+
if (args.namespace !== "file") return;
|
|
33
|
+
const absPath = path.isAbsolute(args.path) ? args.path : path.join(args.resolveDir, args.path);
|
|
34
|
+
return { path: absPath + RESOLVED_SUFFIX, namespace: "inline-tailwind" };
|
|
35
|
+
});
|
|
36
|
+
build.onLoad({ filter: /\.tw-inline$/, namespace: "inline-tailwind" }, (args) => {
|
|
37
|
+
const realPath = args.path.slice(0, -RESOLVED_SUFFIX.length);
|
|
38
|
+
const contents = execFileSync(
|
|
39
|
+
process.execPath,
|
|
40
|
+
[tailwindCliEntry, "-i", realPath, "-m", "--cwd", pluginRoot],
|
|
41
|
+
{ encoding: "utf-8" }
|
|
42
|
+
);
|
|
43
|
+
return { contents, loader: "text" };
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function createPluginTsupConfig(options) {
|
|
49
|
+
const { pluginRoot, entry = ["src/index.ts"], external = [], analyze } = options;
|
|
50
|
+
const shouldAnalyze = analyze ?? process.env.ANALYZE === "true";
|
|
51
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(pluginRoot, "package.json"), "utf-8"));
|
|
52
|
+
return {
|
|
53
|
+
entry,
|
|
54
|
+
format: ["esm"],
|
|
55
|
+
outDir: "dist",
|
|
56
|
+
target: "es2020",
|
|
57
|
+
splitting: true,
|
|
58
|
+
sourcemap: false,
|
|
59
|
+
clean: true,
|
|
60
|
+
metafile: shouldAnalyze,
|
|
61
|
+
external: [...PLUGIN_SHARED_EXTERNALS, ...external],
|
|
62
|
+
// Tailwind CSS is compiled in-memory by the inline-tailwind esbuild plugin
|
|
63
|
+
// (above) and imported as raw text via `import("./style.css")`, so it ends
|
|
64
|
+
// up embedded directly in dist/index.js instead of shipped as a separate
|
|
65
|
+
// stylesheet asset. Must be set here (tsup's top-level `loader` option)
|
|
66
|
+
// rather than inside esbuildOptions — tsup's own CSS-handling esbuild
|
|
67
|
+
// plugin reads this value before esbuildOptions runs.
|
|
68
|
+
loader: {
|
|
69
|
+
".css": "text"
|
|
70
|
+
},
|
|
71
|
+
// tsup's own esbuild-plugin array (postcss, svelte, etc.) is built statically
|
|
72
|
+
// before the build starts; a plugin pushed onto `options.plugins` inside
|
|
73
|
+
// esbuildOptions arrives too late; esbuild has already snapshotted the array
|
|
74
|
+
// for setup. `esbuildPlugins` is tsup's supported hook for adding one upfront.
|
|
75
|
+
esbuildPlugins: [createInlineTailwindPlugin(pluginRoot)],
|
|
76
|
+
esbuildOptions: (esbuildOptions) => {
|
|
77
|
+
esbuildOptions.banner = {
|
|
78
|
+
js: "/* Plugin bundle - loaded dynamically */"
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
onSuccess: async () => {
|
|
82
|
+
const metafilePath = path.join(pluginRoot, "dist", "metafile-esm.json");
|
|
83
|
+
if (shouldAnalyze && fs.existsSync(metafilePath)) {
|
|
84
|
+
const statsDir = path.join(pluginRoot, "dist", "stats");
|
|
85
|
+
fs.mkdirSync(statsDir, { recursive: true });
|
|
86
|
+
const metadata = JSON.parse(fs.readFileSync(metafilePath, "utf-8"));
|
|
87
|
+
const html = await visualizer(metadata, {
|
|
88
|
+
title: `${pkg.name} Bundle Report`,
|
|
89
|
+
template: "treemap"
|
|
90
|
+
});
|
|
91
|
+
fs.writeFileSync(path.join(statsDir, "bundle-report.html"), html);
|
|
92
|
+
fs.writeFileSync(path.join(statsDir, "bundle-stats.json"), prepareVisualizerData(metadata));
|
|
93
|
+
fs.renameSync(metafilePath, path.join(statsDir, "metafile-esm.json"));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { PLUGIN_SHARED_EXTERNALS, createPluginTsupConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litelens/core",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.3",
|
|
4
4
|
"description": "React hooks and utilities for litelens plugin development",
|
|
5
5
|
"private": false,
|
|
6
6
|
"repository": {
|
|
@@ -20,22 +20,31 @@
|
|
|
20
20
|
"exports": {
|
|
21
21
|
".": {
|
|
22
22
|
"import": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./tsup-preset": {
|
|
25
|
+
"import": "./dist/tsup-preset.js"
|
|
23
26
|
}
|
|
24
27
|
},
|
|
25
28
|
"peerDependencies": {
|
|
29
|
+
"@tanstack/react-query": "^5.101.4",
|
|
26
30
|
"react": "^19.0.0",
|
|
27
31
|
"react-dom": "^19.0.0"
|
|
28
32
|
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@tailwindcss/cli": "^4.3.3",
|
|
35
|
+
"esbuild-visualizer": "^0.7.0",
|
|
36
|
+
"tsup": "^8.5.1"
|
|
37
|
+
},
|
|
29
38
|
"devDependencies": {
|
|
39
|
+
"@tanstack/react-query": "^5.101.4",
|
|
30
40
|
"@types/node": "^26.2.0",
|
|
31
41
|
"@types/react": "^19.2.18",
|
|
32
42
|
"@types/react-dom": "^19.2.4",
|
|
33
|
-
"@vitejs/plugin-react": "^6.0
|
|
34
|
-
"@vitest/coverage-v8": "^4.1.
|
|
43
|
+
"@vitejs/plugin-react": "^6.1.0",
|
|
44
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
35
45
|
"jsdom": "^29.1.1",
|
|
36
|
-
"tsup": "^8.5.1",
|
|
37
46
|
"typescript": "^6.0.3",
|
|
38
|
-
"vitest": "^4.1.
|
|
47
|
+
"vitest": "^4.1.11"
|
|
39
48
|
},
|
|
40
49
|
"scripts": {
|
|
41
50
|
"build": "tsup",
|