From dc0d128892da4137591ff910cae01525741b08ee Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Wed, 10 Sep 2025 20:23:12 +0000 Subject: [PATCH] feat(api-client): Add advanced cluster creation method and refactor login actions to use API client --- ts_apiclient/classes.cloudlyapiclient.ts | 8 + ts_web/appstate.ts | 223 ++++++++++------------- 2 files changed, 105 insertions(+), 126 deletions(-) diff --git a/ts_apiclient/classes.cloudlyapiclient.ts b/ts_apiclient/classes.cloudlyapiclient.ts index e8c96f5..2f962f2 100644 --- a/ts_apiclient/classes.cloudlyapiclient.ts +++ b/ts_apiclient/classes.cloudlyapiclient.ts @@ -271,6 +271,14 @@ export class CloudlyApiClient { }, createCluster: async (optionsArg: Parameters[1]) => { return Cluster.createCluster(this, optionsArg); + }, + createClusterAdvanced: async (clusterName: string, setupMode?: 'manual' | 'hetzner' | 'aws' | 'digitalocean') => { + const op = 'createCluster'; + const payload: any = { identity: this.identity, clusterName }; + if (setupMode) payload.setupMode = setupMode; + const wsReq = this.createWsRequest(op); + if (wsReq) return wsReq.fire(payload); + return this.createHttpRequest(op).fire(payload); } } diff --git a/ts_web/appstate.ts b/ts_web/appstate.ts index 09cbe46..654d8e9 100644 --- a/ts_web/appstate.ts +++ b/ts_web/appstate.ts @@ -14,27 +14,19 @@ export const loginStatePart: plugins.smartstate.StatePart export const loginAction = loginStatePart.createAction<{ username: string; password: string }>( async (statePartArg, payloadArg) => { const currentState = statePartArg.getState(); - const trLogin = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'adminLoginWithUsernameAndPassword' - ); - const response = await trLogin.fire({ - username: payloadArg.username, - password: payloadArg.password, - }).catch(err => { + let identity: plugins.interfaces.data.IIdentity = null; + try { + identity = await apiClient.loginWithUsernameAndPassword(payloadArg.username, payloadArg.password) as any; + } catch (err) { console.log(err); - return { - ...statePartArg.getState(), - } - }); + } const newState = { ...currentState, - ...(response.identity ? { identity: response.identity } : {}), + ...(identity ? { identity } : {}), }; try { // Keep shared API client in sync and establish WS for modules using sockets - apiClient.identity = (response as any)?.identity || null; + apiClient.identity = identity || null; if (apiClient.identity) { if (!apiClient['typedsocketClient']) { await apiClient.start(); @@ -105,60 +97,67 @@ export const apiClient = new plugins.servezoneApi.CloudlyApiClient({ export const getAllDataAction = dataState.createAction(async (statePartArg) => { let currentState = statePartArg.getState(); // SecretsGroups - const trGetSecretGroups = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'getSecretGroups' - ); - const response = await trGetSecretGroups.fire({ - identity: loginStatePart.getState().identity, - }); - currentState = { - ...currentState, - secretGroups: response.secretGroups, - }; + try { + apiClient.identity = loginStatePart.getState().identity; + const secretGroups = await apiClient.secretgroup.getSecretGroups(); + currentState = { + ...currentState, + secretGroups: secretGroups as any, + }; + } catch (err) { + console.error('Failed to fetch secret groups:', err); + currentState = { + ...currentState, + secretGroups: [], + }; + } // SecretBundles - const trGetSecretBundles = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'getSecretBundles' - ); - const responseSecretBundles = await trGetSecretBundles.fire({ - identity: loginStatePart.getState().identity, - }); - currentState = { - ...currentState, - secretBundles: responseSecretBundles.secretBundles, - }; + try { + apiClient.identity = loginStatePart.getState().identity; + const responseSecretBundles = await apiClient.secretbundle.getSecretBundles(); + currentState = { + ...currentState, + secretBundles: responseSecretBundles as any, + }; + } catch (err) { + console.error('Failed to fetch secret bundles:', err); + currentState = { + ...currentState, + secretBundles: [], + }; + } // images - const trGetImages = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'getAllImages' - ); - const responseImages = await trGetImages.fire({ - identity: loginStatePart.getState().identity, - }); - currentState = { - ...currentState, - images: responseImages.images, - }; + try { + apiClient.identity = loginStatePart.getState().identity; + const images = await apiClient.image.getImages(); + currentState = { + ...currentState, + images: images as any, + }; + } catch (err) { + console.error('Failed to fetch images:', err); + currentState = { + ...currentState, + images: [], + }; + } // Clusters - const trGetClusters = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'getClusters' - ); - const responseClusters = await trGetClusters.fire({ - identity: loginStatePart.getState().identity, - }); - - currentState = { - ...currentState, - clusters: responseClusters.clusters, + try { + apiClient.identity = loginStatePart.getState().identity; + const clusters = await apiClient.cluster.getClusters(); + currentState = { + ...currentState, + clusters: clusters as any, + } + } catch (err) { + console.error('Failed to fetch clusters:', err); + currentState = { + ...currentState, + clusters: [], + } } // External Registries via shared API client @@ -178,18 +177,12 @@ export const getAllDataAction = dataState.createAction(async (statePartArg) => { } // Services - const trGetServices = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'getServices' - ); try { - const responseServices = await trGetServices.fire({ - identity: loginStatePart.getState().identity, - }); + apiClient.identity = loginStatePart.getState().identity; + const services = await apiClient.services.getServices(); currentState = { ...currentState, - services: responseServices?.services || [], + services: services as any, }; } catch (error) { console.error('Failed to fetch services:', error); @@ -200,15 +193,9 @@ export const getAllDataAction = dataState.createAction(async (statePartArg) => { } // Deployments - const trGetDeployments = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'getDeployments' - ); try { - const responseDeployments = await trGetDeployments.fire({ - identity: loginStatePart.getState().identity, - }); + apiClient.identity = loginStatePart.getState().identity; + const responseDeployments = await apiClient.deployments.getDeployments(); currentState = { ...currentState, deployments: responseDeployments?.deployments || [], @@ -291,16 +278,13 @@ export const deleteServiceAction = dataState.createAction( export const createSecretGroupAction = dataState.createAction( async (statePartArg, payloadArg: plugins.interfaces.data.ISecretGroup) => { let currentState = statePartArg.getState(); - const trCreateSecretGroup = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'createSecretGroup' - ); - const response = await trCreateSecretGroup.fire({ - identity: loginStatePart.getState().identity, - secretGroup: payloadArg, - }); - currentState = await dataState.dispatchAction(getAllDataAction, null); + try { + apiClient.identity = loginStatePart.getState().identity; + await apiClient.secretgroup.createSecretGroup(payloadArg.data); + currentState = await dataState.dispatchAction(getAllDataAction, null); + } catch (err) { + console.error('Failed to create secret group:', err); + } return currentState; return currentState; } @@ -309,16 +293,16 @@ export const createSecretGroupAction = dataState.createAction( export const deleteSecretGroupAction = dataState.createAction( async (statePartArg, payloadArg: { secretGroupId: string }) => { let currentState = statePartArg.getState(); - const trDeleteSecretGroup = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'deleteSecretGroupById' - ); - const response = await trDeleteSecretGroup.fire({ - identity: loginStatePart.getState().identity, - secretGroupId: payloadArg.secretGroupId, - }); - currentState = await dataState.dispatchAction(getAllDataAction, null); + try { + apiClient.identity = loginStatePart.getState().identity; + const sg = (currentState.secretGroups as any[])?.find(s => s.id === payloadArg.secretGroupId); + if (sg) { + await sg.delete(apiClient as any, sg.id); + } + currentState = await dataState.dispatchAction(getAllDataAction, null); + } catch (err) { + console.error('Failed to delete secret group:', err); + } return currentState; } ); @@ -327,16 +311,16 @@ export const deleteSecretGroupAction = dataState.createAction( export const deleteSecretBundleAction = dataState.createAction( async (statePartArg, payloadArg: { configBundleId: string }) => { let currentState = statePartArg.getState(); - const trDeleteConfigBundle = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'deleteSecretBundleById' - ); - const response = await trDeleteConfigBundle.fire({ - identity: loginStatePart.getState().identity, - secretBundleId: payloadArg.configBundleId, - }); - currentState = await dataState.dispatchAction(getAllDataAction, null); + try { + apiClient.identity = loginStatePart.getState().identity; + const sb = (currentState.secretBundles as any[])?.find(b => b.id === payloadArg.configBundleId); + if (sb) { + await sb.delete(apiClient as any, sb.id); + } + currentState = await dataState.dispatchAction(getAllDataAction, null); + } catch (err) { + console.error('Failed to delete secret bundle:', err); + } return currentState; } ); @@ -603,21 +587,8 @@ export const addClusterAction = dataState.createAction( } ) => { let currentState = statePartArg.getState(); - const trAddCluster = - new domtools.plugins.typedrequest.TypedRequest( - '/typedrequest', - 'createCluster' - ); - const response = await trAddCluster.fire({ - identity: loginStatePart.getState().identity, - ...payloadArg, - }); - currentState = { - ...currentState, - ...{ - clusters: [...currentState.clusters, response.cluster], - }, - } - return currentState; + apiClient.identity = loginStatePart.getState().identity; + await apiClient.cluster.createClusterAdvanced(payloadArg.clusterName, payloadArg.setupMode); + return await dataState.dispatchAction(getAllDataAction, null); } );