Files
twenty/packages/twenty-sdk/src/cli/operations/uninstall.ts
T
Charles Bochet 4264741281 Clear stale SDK config on uninstall and invalid client (#19608)
## Summary
- After a successful `uninstall`, clear all app registration config
(`appRegistrationId`, `appRegistrationClientId`, `appAccessToken`,
`appRefreshToken`) so the next `dev` run doesn't hit "app not found"
errors from leftover credentials
- On app re-registration (`ensureAppRegistration`), clear stale
`appAccessToken`/`appRefreshToken` that belonged to the previous
registration
- On OAuth token refresh failure, only clear config when the server
returns `invalid_client` (registration was deleted), not on transient
failures like network issues
- Extract a shared `parse-server-error` utility for consistently parsing
both GraphQL error codes (`extensions.code`/`subCode`) and OAuth error
responses (`error`/`error_description`)
2026-04-12 16:29:29 +02:00

66 lines
1.7 KiB
TypeScript

import { ApiService } from '@/cli/utilities/api/api-service';
import { readManifestFromFile } from '@/cli/utilities/build/manifest/manifest-reader';
import { ConfigService } from '@/cli/utilities/config/config-service';
import { runSafe } from '@/cli/utilities/run-safe';
import { APP_ERROR_CODES, type CommandResult } from '@/cli/types';
export type AppUninstallOptions = {
appPath: string;
remote?: string;
};
const innerAppUninstall = async (
options: AppUninstallOptions,
): Promise<CommandResult> => {
if (options.remote) {
ConfigService.setActiveRemote(options.remote);
}
const configService = new ConfigService();
const apiService = new ApiService();
const manifest = await readManifestFromFile(options.appPath);
if (!manifest) {
return {
success: false,
error: {
code: APP_ERROR_CODES.MANIFEST_NOT_FOUND,
message: 'Manifest not found. Run `build` or `dev` first.',
},
};
}
const result = await apiService.uninstallApplication(
manifest.application.universalIdentifier,
);
if (!result.success) {
const errorMessage =
result.error instanceof Error
? result.error.message
: String(result.error ?? 'Unknown error');
return {
success: false,
error: {
code: APP_ERROR_CODES.UNINSTALL_FAILED,
message: errorMessage,
},
};
}
await configService.setConfig({
appRegistrationId: undefined,
appRegistrationClientId: undefined,
appAccessToken: undefined,
appRefreshToken: undefined,
});
return { success: true, data: undefined };
};
export const appUninstall = (
options: AppUninstallOptions,
): Promise<CommandResult> =>
runSafe(() => innerAppUninstall(options), APP_ERROR_CODES.UNINSTALL_FAILED);