Compare commits
3 commits
develop
...
fix/cache-
Author | SHA1 | Date | |
---|---|---|---|
|
1d8f608936 | ||
|
900c31ec19 | ||
|
c736fff601 |
10 changed files with 101 additions and 104 deletions
|
@ -1,4 +1,4 @@
|
||||||
APPS_REPO_ID=7a92c8307e0a8074763c80be1fcfa4f87da6641daea9211aea6743b0116aba3b
|
APPS_REPO_ID=29ca930bfdaffa1dfabf5726336380ede7066bc53297e3c0c868b27c97282903
|
||||||
APPS_REPO_URL=https://github.com/runtipi/runtipi-appstore
|
APPS_REPO_URL=https://github.com/runtipi/runtipi-appstore
|
||||||
TZ=Etc/UTC
|
TZ=Etc/UTC
|
||||||
INTERNAL_IP=localhost
|
INTERNAL_IP=localhost
|
||||||
|
|
|
@ -23,7 +23,6 @@ import { UpdateModal } from '../UpdateModal';
|
||||||
import { UpdateSettingsModal } from '../UpdateSettingsModal/UpdateSettingsModal';
|
import { UpdateSettingsModal } from '../UpdateSettingsModal/UpdateSettingsModal';
|
||||||
import { AppActions } from '../AppActions';
|
import { AppActions } from '../AppActions';
|
||||||
import { AppDetailsTabs } from '../AppDetailsTabs';
|
import { AppDetailsTabs } from '../AppDetailsTabs';
|
||||||
import { FormValues } from '../InstallForm';
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
app: Awaited<ReturnType<AppService['getApp']>>;
|
app: Awaited<ReturnType<AppService['getApp']>>;
|
||||||
|
@ -42,6 +41,10 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
const updateSettingsDisclosure = useDisclosure();
|
const updateSettingsDisclosure = useDisclosure();
|
||||||
|
|
||||||
const installMutation = useAction(installAppAction, {
|
const installMutation = useAction(installAppAction, {
|
||||||
|
onExecute: () => {
|
||||||
|
setCustomStatus('installing');
|
||||||
|
installDisclosure.close();
|
||||||
|
},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
setCustomStatus(app.status);
|
setCustomStatus(app.status);
|
||||||
|
@ -54,6 +57,10 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const uninstallMutation = useAction(uninstallAppAction, {
|
const uninstallMutation = useAction(uninstallAppAction, {
|
||||||
|
onExecute: () => {
|
||||||
|
setCustomStatus('uninstalling');
|
||||||
|
uninstallDisclosure.close();
|
||||||
|
},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
setCustomStatus(app.status);
|
setCustomStatus(app.status);
|
||||||
|
@ -66,6 +73,10 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const stopMutation = useAction(stopAppAction, {
|
const stopMutation = useAction(stopAppAction, {
|
||||||
|
onExecute: () => {
|
||||||
|
setCustomStatus('stopping');
|
||||||
|
stopDisclosure.close();
|
||||||
|
},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
setCustomStatus(app.status);
|
setCustomStatus(app.status);
|
||||||
|
@ -78,6 +89,9 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const startMutation = useAction(startAppAction, {
|
const startMutation = useAction(startAppAction, {
|
||||||
|
onExecute: () => {
|
||||||
|
setCustomStatus('starting');
|
||||||
|
},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
setCustomStatus(app.status);
|
setCustomStatus(app.status);
|
||||||
|
@ -90,6 +104,10 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateMutation = useAction(updateAppAction, {
|
const updateMutation = useAction(updateAppAction, {
|
||||||
|
onExecute: () => {
|
||||||
|
setCustomStatus('updating');
|
||||||
|
updateDisclosure.close();
|
||||||
|
},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
setCustomStatus(app.status);
|
setCustomStatus(app.status);
|
||||||
|
@ -102,6 +120,9 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateConfigMutation = useAction(updateAppConfigAction, {
|
const updateConfigMutation = useAction(updateAppConfigAction, {
|
||||||
|
onExecute: () => {
|
||||||
|
updateSettingsDisclosure.close();
|
||||||
|
},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
toast.error(data.failure.reason);
|
toast.error(data.failure.reason);
|
||||||
|
@ -113,40 +134,6 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
|
|
||||||
const updateAvailable = Number(app.version || 0) < Number(app?.latestVersion || 0);
|
const updateAvailable = Number(app.version || 0) < Number(app?.latestVersion || 0);
|
||||||
|
|
||||||
const handleInstallSubmit = async (values: FormValues) => {
|
|
||||||
setCustomStatus('installing');
|
|
||||||
installDisclosure.close();
|
|
||||||
installMutation.execute({ id: app.id, form: values });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleUnistallSubmit = () => {
|
|
||||||
setCustomStatus('uninstalling');
|
|
||||||
uninstallDisclosure.close();
|
|
||||||
uninstallMutation.execute({ id: app.id });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStopSubmit = () => {
|
|
||||||
setCustomStatus('stopping');
|
|
||||||
stopDisclosure.close();
|
|
||||||
stopMutation.execute({ id: app.id });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStartSubmit = async () => {
|
|
||||||
setCustomStatus('starting');
|
|
||||||
startMutation.execute({ id: app.id });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleUpdateSettingsSubmit = async (values: FormValues) => {
|
|
||||||
updateSettingsDisclosure.close();
|
|
||||||
updateConfigMutation.execute({ id: app.id, form: values });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleUpdateSubmit = async () => {
|
|
||||||
setCustomStatus('updating');
|
|
||||||
updateDisclosure.close();
|
|
||||||
updateMutation.execute({ id: app.id });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleOpen = (type: OpenType) => {
|
const handleOpen = (type: OpenType) => {
|
||||||
let url = '';
|
let url = '';
|
||||||
const { https } = app.info;
|
const { https } = app.info;
|
||||||
|
@ -173,12 +160,12 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card" data-testid="app-details">
|
<div className="card" data-testid="app-details">
|
||||||
<InstallModal onSubmit={handleInstallSubmit} isOpen={installDisclosure.isOpen} onClose={installDisclosure.close} info={app.info} />
|
<InstallModal onSubmit={(form) => installMutation.execute({ id: app.id, form })} isOpen={installDisclosure.isOpen} onClose={installDisclosure.close} info={app.info} />
|
||||||
<StopModal onConfirm={handleStopSubmit} isOpen={stopDisclosure.isOpen} onClose={stopDisclosure.close} info={app.info} />
|
<StopModal onConfirm={() => stopMutation.execute({ id: app.id })} isOpen={stopDisclosure.isOpen} onClose={stopDisclosure.close} info={app.info} />
|
||||||
<UninstallModal onConfirm={handleUnistallSubmit} isOpen={uninstallDisclosure.isOpen} onClose={uninstallDisclosure.close} info={app.info} />
|
<UninstallModal onConfirm={() => uninstallMutation.execute({ id: app.id })} isOpen={uninstallDisclosure.isOpen} onClose={uninstallDisclosure.close} info={app.info} />
|
||||||
<UpdateModal onConfirm={handleUpdateSubmit} isOpen={updateDisclosure.isOpen} onClose={updateDisclosure.close} info={app.info} newVersion={newVersion} />
|
<UpdateModal onConfirm={() => updateMutation.execute({ id: app.id })} isOpen={updateDisclosure.isOpen} onClose={updateDisclosure.close} info={app.info} newVersion={newVersion} />
|
||||||
<UpdateSettingsModal
|
<UpdateSettingsModal
|
||||||
onSubmit={handleUpdateSettingsSubmit}
|
onSubmit={(form) => updateConfigMutation.execute({ id: app.id, form })}
|
||||||
isOpen={updateSettingsDisclosure.isOpen}
|
isOpen={updateSettingsDisclosure.isOpen}
|
||||||
onClose={updateSettingsDisclosure.close}
|
onClose={updateSettingsDisclosure.close}
|
||||||
info={app.info}
|
info={app.info}
|
||||||
|
@ -203,7 +190,7 @@ export const AppDetailsContainer: React.FC<IProps> = ({ app, localDomain }) => {
|
||||||
onUninstall={uninstallDisclosure.open}
|
onUninstall={uninstallDisclosure.open}
|
||||||
onInstall={installDisclosure.open}
|
onInstall={installDisclosure.open}
|
||||||
onOpen={handleOpen}
|
onOpen={handleOpen}
|
||||||
onStart={handleStartSubmit}
|
onStart={() => startMutation.execute({ id: app.id })}
|
||||||
app={app}
|
app={app}
|
||||||
status={customStatus}
|
status={customStatus}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { db } from '@/server/db';
|
|
||||||
import { action } from '@/lib/safe-action';
|
import { action } from '@/lib/safe-action';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
||||||
|
@ -19,16 +18,15 @@ const input = z.object({
|
||||||
*/
|
*/
|
||||||
export const installAppAction = action(input, async ({ id, form }) => {
|
export const installAppAction = action(input, async ({ id, form }) => {
|
||||||
try {
|
try {
|
||||||
const appsService = new AppServiceClass(db);
|
const appsService = new AppServiceClass();
|
||||||
|
|
||||||
await appsService.installApp(id, form);
|
await appsService.installApp(id, form);
|
||||||
|
|
||||||
revalidatePath('/apps');
|
|
||||||
revalidatePath(`/app/${id}`);
|
|
||||||
revalidatePath(`/app-store/${id}`);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e);
|
return await handleActionError(e);
|
||||||
|
} finally {
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { db } from '@/server/db';
|
|
||||||
import { action } from '@/lib/safe-action';
|
import { action } from '@/lib/safe-action';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
||||||
|
@ -14,16 +13,15 @@ const input = z.object({ id: z.string() });
|
||||||
*/
|
*/
|
||||||
export const startAppAction = action(input, async ({ id }) => {
|
export const startAppAction = action(input, async ({ id }) => {
|
||||||
try {
|
try {
|
||||||
const appsService = new AppServiceClass(db);
|
const appsService = new AppServiceClass();
|
||||||
|
|
||||||
await appsService.startApp(id);
|
await appsService.startApp(id);
|
||||||
|
|
||||||
revalidatePath('/apps');
|
|
||||||
revalidatePath(`/app/${id}`);
|
|
||||||
revalidatePath(`/app-store/${id}`);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e);
|
return await handleActionError(e);
|
||||||
|
} finally {
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { db } from '@/server/db';
|
|
||||||
import { action } from '@/lib/safe-action';
|
import { action } from '@/lib/safe-action';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
||||||
|
@ -14,16 +13,15 @@ const input = z.object({ id: z.string() });
|
||||||
*/
|
*/
|
||||||
export const stopAppAction = action(input, async ({ id }) => {
|
export const stopAppAction = action(input, async ({ id }) => {
|
||||||
try {
|
try {
|
||||||
const appsService = new AppServiceClass(db);
|
const appsService = new AppServiceClass();
|
||||||
|
|
||||||
await appsService.stopApp(id);
|
await appsService.stopApp(id);
|
||||||
|
|
||||||
revalidatePath('/apps');
|
|
||||||
revalidatePath(`/app/${id}`);
|
|
||||||
revalidatePath(`/app-store/${id}`);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e);
|
return await handleActionError(e);
|
||||||
|
} finally {
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { db } from '@/server/db';
|
|
||||||
import { action } from '@/lib/safe-action';
|
import { action } from '@/lib/safe-action';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
||||||
|
@ -14,16 +13,15 @@ const input = z.object({ id: z.string() });
|
||||||
*/
|
*/
|
||||||
export const uninstallAppAction = action(input, async ({ id }) => {
|
export const uninstallAppAction = action(input, async ({ id }) => {
|
||||||
try {
|
try {
|
||||||
const appsService = new AppServiceClass(db);
|
const appsService = new AppServiceClass();
|
||||||
|
|
||||||
await appsService.uninstallApp(id);
|
await appsService.uninstallApp(id);
|
||||||
|
|
||||||
revalidatePath('/apps');
|
|
||||||
revalidatePath(`/app/${id}`);
|
|
||||||
revalidatePath(`/app-store/${id}`);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e);
|
return await handleActionError(e);
|
||||||
|
} finally {
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { db } from '@/server/db';
|
|
||||||
import { action } from '@/lib/safe-action';
|
import { action } from '@/lib/safe-action';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
||||||
|
@ -14,16 +13,15 @@ const input = z.object({ id: z.string() });
|
||||||
*/
|
*/
|
||||||
export const updateAppAction = action(input, async ({ id }) => {
|
export const updateAppAction = action(input, async ({ id }) => {
|
||||||
try {
|
try {
|
||||||
const appsService = new AppServiceClass(db);
|
const appsService = new AppServiceClass();
|
||||||
|
|
||||||
await appsService.updateApp(id);
|
await appsService.updateApp(id);
|
||||||
|
|
||||||
revalidatePath('/apps');
|
|
||||||
revalidatePath(`/app/${id}`);
|
|
||||||
revalidatePath(`/app-store/${id}`);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e);
|
return await handleActionError(e);
|
||||||
|
} finally {
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { db } from '@/server/db';
|
|
||||||
import { action } from '@/lib/safe-action';
|
import { action } from '@/lib/safe-action';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
import { AppServiceClass } from '@/server/services/apps/apps.service';
|
||||||
|
@ -21,16 +20,15 @@ const input = z.object({
|
||||||
*/
|
*/
|
||||||
export const updateAppConfigAction = action(input, async ({ id, form }) => {
|
export const updateAppConfigAction = action(input, async ({ id, form }) => {
|
||||||
try {
|
try {
|
||||||
const appsService = new AppServiceClass(db);
|
const appsService = new AppServiceClass();
|
||||||
|
|
||||||
await appsService.updateAppConfig(id, form);
|
await appsService.updateAppConfig(id, form);
|
||||||
|
|
||||||
revalidatePath('/apps');
|
|
||||||
revalidatePath(`/app/${id}`);
|
|
||||||
revalidatePath(`/app-store/${id}`);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e);
|
return await handleActionError(e);
|
||||||
|
} finally {
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { and, asc, eq, ne, notInArray } from 'drizzle-orm';
|
import { and, asc, eq, ne, notInArray } from 'drizzle-orm';
|
||||||
import { Database } from '@/server/db';
|
import { Database, db } from '@/server/db';
|
||||||
import { appTable, NewApp, AppStatus } from '../../db/schema';
|
import { appTable, NewApp, AppStatus } from '../../db/schema';
|
||||||
|
|
||||||
export class AppQueries {
|
export class AppQueries {
|
||||||
private db;
|
private db;
|
||||||
|
|
||||||
constructor(p: Database) {
|
constructor(p: Database = db) {
|
||||||
this.db = p;
|
this.db = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Database } from '@/server/db';
|
||||||
import { AppInfo } from '@runtipi/shared';
|
import { AppInfo } from '@runtipi/shared';
|
||||||
import { EventDispatcher } from '@/server/core/EventDispatcher/EventDispatcher';
|
import { EventDispatcher } from '@/server/core/EventDispatcher/EventDispatcher';
|
||||||
import { castAppConfig } from '@/lib/helpers/castAppConfig';
|
import { castAppConfig } from '@/lib/helpers/castAppConfig';
|
||||||
|
import { revalidatePath } from 'next/cache';
|
||||||
import { checkAppRequirements, getAvailableApps, getAppInfo, getUpdateInfo } from './apps.helpers';
|
import { checkAppRequirements, getAvailableApps, getAppInfo, getUpdateInfo } from './apps.helpers';
|
||||||
import { getConfig } from '../../core/TipiConfig';
|
import { getConfig } from '../../core/TipiConfig';
|
||||||
import { Logger } from '../../core/Logger';
|
import { Logger } from '../../core/Logger';
|
||||||
|
@ -32,7 +33,7 @@ const filterApps = (apps: AppInfo[]): AppInfo[] => apps.sort(sortApps).filter(fi
|
||||||
export class AppServiceClass {
|
export class AppServiceClass {
|
||||||
private queries;
|
private queries;
|
||||||
|
|
||||||
constructor(p: Database) {
|
constructor(p?: Database) {
|
||||||
this.queries = new AppQueries(p);
|
this.queries = new AppQueries(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,29 +77,34 @@ export class AppServiceClass {
|
||||||
* This function starts an app specified by its appName, regenerates its environment file and checks for missing requirements.
|
* This function starts an app specified by its appName, regenerates its environment file and checks for missing requirements.
|
||||||
* It updates the app's status in the database to 'starting' and 'running' if the start process is successful, otherwise it updates the status to 'stopped'.
|
* It updates the app's status in the database to 'starting' and 'running' if the start process is successful, otherwise it updates the status to 'stopped'.
|
||||||
*
|
*
|
||||||
* @param {string} appName - The name of the app to start
|
* @param {string} id - The name of the app to start
|
||||||
* @throws {Error} - If the app is not found or the start process fails.
|
* @throws {Error} - If the app is not found or the start process fails.
|
||||||
*/
|
*/
|
||||||
public startApp = async (appName: string) => {
|
public startApp = async (id: string) => {
|
||||||
const app = await this.queries.getApp(appName);
|
const app = await this.queries.getApp(id);
|
||||||
if (!app) {
|
if (!app) {
|
||||||
throw new TranslatedError('server-messages.errors.app-not-found', { id: appName });
|
throw new TranslatedError('server-messages.errors.app-not-found', { id });
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.queries.updateApp(appName, { status: 'starting' });
|
await this.queries.updateApp(id, { status: 'starting' });
|
||||||
|
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
|
|
||||||
const eventDispatcher = new EventDispatcher('startApp');
|
const eventDispatcher = new EventDispatcher('startApp');
|
||||||
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'start', appid: appName, form: castAppConfig(app.config) });
|
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'start', appid: id, form: castAppConfig(app.config) });
|
||||||
await eventDispatcher.close();
|
await eventDispatcher.close();
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
await this.queries.updateApp(appName, { status: 'running' });
|
await this.queries.updateApp(id, { status: 'running' });
|
||||||
} else {
|
} else {
|
||||||
await this.queries.updateApp(appName, { status: 'stopped' });
|
await this.queries.updateApp(id, { status: 'stopped' });
|
||||||
Logger.error(`Failed to start app ${appName}: ${stdout}`);
|
Logger.error(`Failed to start app ${id}: ${stdout}`);
|
||||||
throw new TranslatedError('server-messages.errors.app-failed-to-start', { id: appName });
|
throw new TranslatedError('server-messages.errors.app-failed-to-start', { id });
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedApp = await this.queries.getApp(appName);
|
const updatedApp = await this.queries.getApp(id);
|
||||||
return updatedApp;
|
return updatedApp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -164,6 +170,10 @@ export class AppServiceClass {
|
||||||
isVisibleOnGuestDashboard,
|
isVisibleOnGuestDashboard,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
|
|
||||||
// Run script
|
// Run script
|
||||||
const eventDispatcher = new EventDispatcher('installApp');
|
const eventDispatcher = new EventDispatcher('installApp');
|
||||||
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'install', appid: id, form });
|
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'install', appid: id, form });
|
||||||
|
@ -263,6 +273,10 @@ export class AppServiceClass {
|
||||||
// Run script
|
// Run script
|
||||||
await this.queries.updateApp(id, { status: 'stopping' });
|
await this.queries.updateApp(id, { status: 'stopping' });
|
||||||
|
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
|
|
||||||
const eventDispatcher = new EventDispatcher('stopApp');
|
const eventDispatcher = new EventDispatcher('stopApp');
|
||||||
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'stop', appid: id, form: castAppConfig(app.config) });
|
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'stop', appid: id, form: castAppConfig(app.config) });
|
||||||
await eventDispatcher.close();
|
await eventDispatcher.close();
|
||||||
|
@ -297,6 +311,10 @@ export class AppServiceClass {
|
||||||
|
|
||||||
await this.queries.updateApp(id, { status: 'uninstalling' });
|
await this.queries.updateApp(id, { status: 'uninstalling' });
|
||||||
|
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
|
|
||||||
const eventDispatcher = new EventDispatcher('uninstallApp');
|
const eventDispatcher = new EventDispatcher('uninstallApp');
|
||||||
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'uninstall', appid: id, form: castAppConfig(app.config) });
|
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'uninstall', appid: id, form: castAppConfig(app.config) });
|
||||||
await eventDispatcher.close();
|
await eventDispatcher.close();
|
||||||
|
@ -348,6 +366,10 @@ export class AppServiceClass {
|
||||||
|
|
||||||
await this.queries.updateApp(id, { status: 'updating' });
|
await this.queries.updateApp(id, { status: 'updating' });
|
||||||
|
|
||||||
|
revalidatePath('/apps');
|
||||||
|
revalidatePath(`/app/${id}`);
|
||||||
|
revalidatePath(`/app-store/${id}`);
|
||||||
|
|
||||||
const eventDispatcher = new EventDispatcher('updateApp');
|
const eventDispatcher = new EventDispatcher('updateApp');
|
||||||
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'update', appid: id, form: castAppConfig(app.config) });
|
const { success, stdout } = await eventDispatcher.dispatchEventAsync({ type: 'app', command: 'update', appid: id, form: castAppConfig(app.config) });
|
||||||
await eventDispatcher.close();
|
await eventDispatcher.close();
|
||||||
|
|
Loading…
Reference in a new issue