Skip to content

Commit ab12f11

Browse files
authored
feat: add api module (#445)
Signed-off-by: Philippe Martin <[email protected]>
1 parent df49d83 commit ab12f11

File tree

14 files changed

+206
-11
lines changed

14 files changed

+206
-11
lines changed

.github/workflows/release.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ jobs:
6868
sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.extVersion }}\",#g" package.json
6969
sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.extVersion }}\",#g" packages/extension/package.json
7070
sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.extVersion }}\",#g" packages/webview/package.json
71+
sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.extVersion }}\",#g" packages/api/package.json
7172
sed -i "s#\(ghcr.io/podman-desktop/podman-desktop-extension-kubernetes-dashboard-builder:\)next#\1${{ steps.TAG_UTIL.outputs.extVersion }}#g" build/Containerfile
7273
7374
git add package.json packages/extension/package.json packages/webview/package.json build/Containerfile

build/Containerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ RUN mkdir /opt/app-root/extension && \
4343
mkdir -p /opt/app-root/extension/packages/rpc/ && \
4444
cp packages/rpc/package.json /opt/app-root/extension/packages/rpc/ && \
4545
mkdir -p /opt/app-root/extension/packages/channels/ && \
46-
cp packages/channels/package.json /opt/app-root/extension/packages/channels/
46+
cp packages/channels/package.json /opt/app-root/extension/packages/channels/ && \
47+
mkdir -p /opt/app-root/extension/packages/api/ && \
48+
cp packages/api/package.json /opt/app-root/extension/packages/api/
4749

4850
COPY LICENSE /opt/app-root/extension/
4951
COPY README.md /opt/app-root/extension/

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
},
3232
"devDependencies": {
3333
"@eslint/compat": "^1.4.1",
34+
"@tsconfig/strictest": "^2.0.6",
3435
"@typescript-eslint/eslint-plugin": "^8.46.1",
3536
"@typescript-eslint/parser": "^8.30.1",
3637
"@vitest/coverage-v8": "^3.2.2",

packages/api/package.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "@podman-desktop/kubernetes-dashboard-extension-api",
3+
"version": "0.2.0-next",
4+
"description": "API for Kubernetes Dashboard extension",
5+
"repository": "https://github.com/podman-desktop/extension-kubernetes-dashboard",
6+
"publishConfig": {
7+
"provenance": true,
8+
"access": "public"
9+
},
10+
"license": "Apache-2.0",
11+
"types": "./src/kubernetes-dashboard-extension-api.d.ts",
12+
"files": [
13+
"src"
14+
],
15+
"scripts": {
16+
"prepare": "",
17+
"clean": "rimraf lib *.tsbuildinfo",
18+
"build": "",
19+
"watch": "",
20+
"publish:next": "pnpm publish --registry=https://registry.npmjs.org/ --no-git-tag-version --new-version 0.0.1-\"$(date +%s)\""
21+
},
22+
"dependencies": {}
23+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
/**
20+
* The subscriber for the events emitted by the Kubernetes Dashboard extension.
21+
*/
22+
export interface KubernetesDashboardSubscriber {
23+
/**
24+
* Disposes the subscriber and unsubscribes from all the events emitted by the Kubernetes Dashboard extension.
25+
*/
26+
dispose(): void;
27+
}
28+
29+
/**
30+
* The API for the Kubernetes Dashboard extension.
31+
*
32+
* How to use it from your extension:
33+
*
34+
* ```typescript
35+
* import * as extensionApi from '@podman-desktop/api';
36+
*
37+
* export async function activate(extensionContext: ExtensionContext): Promise<void> {
38+
* const didChangeSubscription = extensionApi.extensions.onDidChange(() => {
39+
* const api = extensionApi.extensions.getExtension<KubernetesDashboardExtensionApi>('redhat.kubernetes-dashboard')?.exports;
40+
* if (api) {
41+
* const subscriber = api.getSubscriber();
42+
* // dispose the subscriber when the extension is deactivated
43+
* extensionContext.subscriptions.push(subscriber);
44+
* // stop being notified when the extension is changed
45+
* didChangeSubscription.dispose();
46+
* }
47+
* });
48+
* // stop being notified when the extension is deactivated
49+
* extensionContext.subscriptions.push(didChangeSubscription);
50+
* }
51+
* ```
52+
*/
53+
export interface KubernetesDashboardExtensionApi {
54+
/**
55+
* Returns a subscriber for the events emitted by the Kubernetes Dashboard extension.
56+
*
57+
* The subscriber is used to subscribe to the events emitted by the Kubernetes Dashboard extension.
58+
*/
59+
getSubscriber(): KubernetesDashboardSubscriber;
60+
}

packages/api/tsconfig.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "@tsconfig/strictest/tsconfig.json",
3+
"compilerOptions": {
4+
"target": "esnext",
5+
"module": "node16",
6+
"baseUrl": ".",
7+
"types": ["node"],
8+
"strict": true,
9+
"esModuleInterop": true,
10+
"forceConsistentCasingInFileNames": true
11+
},
12+
"include": ["src/**/*.d.ts"]
13+
}

packages/api/vite.config.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
/* eslint-env node */
19+
import { defineConfig } from 'vite';
20+
21+
const PACKAGE_ROOT = __dirname;
22+
23+
// https://vitejs.dev/config/
24+
export default defineConfig({
25+
mode: process.env.MODE,
26+
root: PACKAGE_ROOT,
27+
base: '',
28+
server: {
29+
fs: {
30+
strict: true,
31+
},
32+
},
33+
build: {
34+
sourcemap: true,
35+
outDir: 'dist',
36+
assetsDir: '.',
37+
emptyOutDir: true,
38+
reportCompressedSize: false,
39+
},
40+
});

packages/channels/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
},
2626
"devDependencies": {
2727
"@kubernetes-dashboard/rpc": "workspace:*",
28+
"@podman-desktop/kubernetes-dashboard-extension-api": "workspace:*",
2829
"vite-plugin-dts": "^4.5.4"
2930
}
3031
}

packages/extension/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
"vite": "^7.2",
4343
"vitest": "^3.1",
4444
"isomorphic-ws": "^5.0.0",
45-
"@types/ws": "^8.18.0"
45+
"@types/ws": "^8.18.0",
46+
"@podman-desktop/kubernetes-dashboard-extension-api": "workspace:*"
4647
},
4748
"dependencies": {
4849
"@kubernetes/client-node": "^1.4.0",

packages/extension/src/dashboard-extension.spec.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { vol } from 'memfs';
2424

2525
import { ContextsManager } from '/@/manager/contexts-manager';
2626
import { ContextsStatesDispatcher } from '/@/manager/contexts-states-dispatcher';
27+
import { type ApiSubscriber } from '/@/subscriber/api-subscriber';
2728

2829
let extensionContextMock: ExtensionContext;
2930
let dashboardExtension: DashboardExtension;
@@ -35,11 +36,15 @@ vi.mock(import('node:fs/promises'));
3536
vi.mock(import('@kubernetes/client-node'));
3637
vi.mock(import('./manager/contexts-manager'));
3738
vi.mock(import('./manager/contexts-states-dispatcher'));
39+
vi.mock(import('./subscriber/api-subscriber'));
3840

3941
beforeEach(() => {
4042
vi.restoreAllMocks();
4143
vi.resetAllMocks();
4244
vol.reset();
45+
vol.fromJSON({
46+
'/path/to/extension/index.html': '<html></html>',
47+
});
4348

4449
vi.mocked(window.createWebviewPanel).mockReturnValue({
4550
webview: {
@@ -63,6 +68,7 @@ beforeEach(() => {
6368

6469
contextsStatesDispatcherMock = {
6570
init: vi.fn(),
71+
addSubscriber: vi.fn(),
6672
} as unknown as ContextsStatesDispatcher;
6773
vi.mocked(ContextsStatesDispatcher).mockReturnValue(contextsStatesDispatcherMock);
6874

@@ -73,12 +79,6 @@ beforeEach(() => {
7379
});
7480

7581
describe('a kubeconfig file is not present', () => {
76-
beforeEach(() => {
77-
vol.fromJSON({
78-
'/path/to/extension/index.html': '<html></html>',
79-
});
80-
});
81-
8282
test('should activate correctly and calls contextsManager every time the kubeconfig file changes', async () => {
8383
await dashboardExtension.activate();
8484
expect(contextsManagerMock.update).not.toHaveBeenCalled();
@@ -126,3 +126,18 @@ describe('a kubeconfig file is present', () => {
126126
expect(p).toBeUndefined();
127127
});
128128
});
129+
130+
test('activate should return a KubernetesDashboardExtensionApi', async () => {
131+
const api = await dashboardExtension.activate();
132+
expect(api).toBeDefined();
133+
expect(api.getSubscriber).toBeDefined();
134+
135+
const subscriber = api.getSubscriber();
136+
expect(subscriber).toBeDefined();
137+
expect(contextsStatesDispatcherMock.addSubscriber).toHaveBeenCalled();
138+
const apiSubscriber = vi.mocked(contextsStatesDispatcherMock.addSubscriber).mock.lastCall?.[0];
139+
140+
subscriber.dispose();
141+
expect(apiSubscriber).toBeDefined();
142+
expect((apiSubscriber as ApiSubscriber).dispose).toHaveBeenCalledOnce();
143+
});

0 commit comments

Comments
 (0)