diff --git a/package.json b/package.json index 492ac30..73b2f6e 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ }, "scripts": { "start": "tsup --watch", + "prepublish": "tsup", "build": "tsup", "lint": "eslint src --ext .ts --quiet", "typings": "tsc", diff --git a/src/data-provider/index.ts b/src/data-provider/index.ts index 3da4787..b29562a 100644 --- a/src/data-provider/index.ts +++ b/src/data-provider/index.ts @@ -8,7 +8,7 @@ import { CreateResponse, MetaQuery, UpdateResponse, - DeleteOneResponse + DeleteOneResponse, } from '@refinedev/core'; import { KubeSdk, Unstructured } from '../kube-api'; import { filterData } from '../utils/filter-data'; @@ -46,8 +46,8 @@ export const dataProvider = ( item.metadata.name === name && item.metadata.namespace === namespace ); if (!data) { - console.error(`resource: ${resource} not include id: ${id}`) - return { data: null as unknown as TData } + console.error(`resource: ${resource} not include id: ${id}`); + return { data: null as unknown as TData }; } return { data: { @@ -87,27 +87,35 @@ export const dataProvider = ( }; }, - getMany: async (params: { + getMany: async < + TData extends BaseRecord = BaseRecord, + TVariables = unknown + >(params: { resource: string; ids: BaseKey[]; variables?: TVariables | undefined; meta?: MetaQuery | undefined; metaData?: MetaQuery | undefined; }): Promise> => { - const { ids, ...rest } = params + const { ids, ...rest } = params; const data = await Promise.all( ids.map(id => getOne({ id, ...rest }).then(v => v.data)) ); return { - data: data as unknown as TData[], + data: data as unknown as TData[], }; }, - create: async ({ variables, meta }:Parameters['0']): Promise> => { + create: async ({ + variables, + meta, + }: Parameters['0']): Promise< + CreateResponse + > => { const sdk = new KubeSdk({ basePath: globalStore.apiUrl, - fieldManager: globalStore.fieldManager + fieldManager: globalStore.fieldManager, }); const data = await sdk.applyYaml([ @@ -123,10 +131,15 @@ export const dataProvider = ( }; }, - update: async ({ variables, meta }:Parameters['0']): Promise> => { + update: async ({ + variables, + meta, + }: Parameters['0']): Promise< + UpdateResponse + > => { const sdk = new KubeSdk({ basePath: globalStore.apiUrl, - fieldManager: globalStore.fieldManager + fieldManager: globalStore.fieldManager, }); const params = [ { @@ -134,8 +147,12 @@ export const dataProvider = ( apiVersion: getApiVersion(meta?.resourceBasePath), kind: meta?.kind, }, - ] - const data = await sdk.applyYaml(params, meta?.strategy, meta?.replacePaths); + ]; + const data = await sdk.applyYaml( + params, + meta?.strategy, + meta?.replacePaths + ); return { data: data[0] as unknown as TData, @@ -144,10 +161,17 @@ export const dataProvider = ( getOne, - deleteOne: async ({ resource, id, meta, ...rest }:Parameters['0']): Promise> => { + deleteOne: async ({ + resource, + id, + meta, + ...rest + }: Parameters['0']): Promise< + DeleteOneResponse + > => { const sdk = new KubeSdk({ basePath: globalStore.apiUrl, - fieldManager: globalStore.fieldManager + fieldManager: globalStore.fieldManager, }); const { data: current } = await getOne({ id, resource, meta, ...rest }); diff --git a/src/global-store.ts b/src/global-store.ts index 091cf37..4c19bba 100644 --- a/src/global-store.ts +++ b/src/global-store.ts @@ -1,5 +1,10 @@ import { MetaQuery } from '@refinedev/core'; -import { KubeApi, UnstructuredList, WatchEvent } from './kube-api'; +import { + KubeApi, + UnstructuredList, + WatchEvent, + StopWatchHandler, +} from './kube-api'; import { relationPlugin } from './plugins/relation'; export function getObjectConstructor(resource: string, meta?: MetaQuery) { @@ -30,6 +35,8 @@ export class GlobalStore { private store = new Map(); private subscribers = new Map void)[]>(); + private kubeApi?: KubeApi; + private stopWatch?: StopWatchHandler; constructor(params: GlobalStoreInitParams) { this.init(params); @@ -40,7 +47,7 @@ export class GlobalStore { get(resource: string, meta?: MetaQuery): Promise { return new Promise((resolve, reject) => { if (!this.store.has(resource)) { - const api = new KubeApi({ + this.kubeApi = new KubeApi({ basePath: this._apiUrl, watchWsBasePath: this.watchWsApiUrl, objectConstructor: getObjectConstructor(resource, meta), @@ -48,7 +55,7 @@ export class GlobalStore { let resolved = false; - api + this.kubeApi .listWatch({ onResponse: res => { relationPlugin.processData(res); @@ -63,6 +70,9 @@ export class GlobalStore { this.notify(resource, event); }, }) + .then(stop => { + this.stopWatch = stop; + }) .catch(e => reject(e)); } else { resolve(this.store.get(resource)! as unknown as T); @@ -98,6 +108,7 @@ export class GlobalStore { this.notify(resource, data); } init(params: GlobalStoreInitParams) { + this.destroy(); const { apiUrl, watchWsApiUrl, prefix, fieldManager } = params; this.store = new Map(); this.subscribers = new Map(); @@ -106,4 +117,9 @@ export class GlobalStore { this.prefix = prefix; this.fieldManager = fieldManager; } + destroy() { + this.store.clear(); + this.subscribers.clear(); + this.stopWatch?.(); + } } diff --git a/src/kube-api.ts b/src/kube-api.ts index 832e77b..54b6d5c 100644 --- a/src/kube-api.ts +++ b/src/kube-api.ts @@ -386,7 +386,6 @@ export class KubeApi { stops.push(this.watchByHttp(url, response, handleEvent, retry)); } } - return () => { stops.forEach(stop => stop()); }; @@ -433,7 +432,7 @@ export class KubeApi { let shouldCloseAfterConnected = false; let stopWatch: () => void = () => { if (socket.readyState === socket.OPEN) { - socket.close(3001, 'DOVETAIL_MANUAL_CLOSE'); + socket.close(3001, 'KUBEAPI_MANUAL_CLOSE'); } else { shouldCloseAfterConnected = true; } @@ -445,7 +444,7 @@ export class KubeApi { socket.addEventListener('open', () => { if (shouldCloseAfterConnected) { - socket.close(3001, 'DOVETAIL_MANUAL_CLOSE'); + socket.close(3001, 'KUBEAPI_MANUAL_CLOSE'); return; } heartbeat(socket); @@ -459,7 +458,7 @@ export class KubeApi { socket.addEventListener('close', evt => { clearTimeout((socket as ExtendedWebsocketClient).pingTimeout); - if (evt.reason === 'DOVETAIL_MANUAL_CLOSE') { + if (evt.reason === 'KUBEAPI_MANUAL_CLOSE') { return; } @@ -661,11 +660,7 @@ export class KubeSdk { } const response = exist - ? await this.patch( - spec, - strategy, - replacePaths?.[index] - ) + ? await this.patch(spec, strategy, replacePaths?.[index]) : await this.create(spec); if (exist) { diff --git a/src/utils/filter-data.ts b/src/utils/filter-data.ts index de8b2aa..d238501 100644 --- a/src/utils/filter-data.ts +++ b/src/utils/filter-data.ts @@ -21,7 +21,7 @@ function deepFilter(item: Unstructured, filter: CrudFilter): boolean { export const filterData = ( filters: CrudFilters, - data: Unstructured[], + data: Unstructured[] ): Unstructured[] => { if (!filters || filters.length === 0) { return data; @@ -35,7 +35,7 @@ export function evaluateFilter( field: string, operator: Exclude, // eslint-disable-next-line @typescript-eslint/no-explicit-any - value: any, + value: any ): boolean { if (!_.has(item, field)) { return false; diff --git a/src/utils/paginate-data.ts b/src/utils/paginate-data.ts index 2adb6ef..e04febd 100644 --- a/src/utils/paginate-data.ts +++ b/src/utils/paginate-data.ts @@ -7,10 +7,8 @@ export const paginateData = ( ): Unstructured[] => { const { current = 1, pageSize = 20, mode } = pagination ?? {}; if (mode !== 'client') { - console.warn( - 'k8s no support server paginateData' - ); - return data + console.warn('k8s no support server paginateData'); + return data; } let start = 0; let end = data.length;