fix(sdk): link dev UI to workspace application detail page (#20849)
sdk handle auth of one workspace per session -- but server could be configured as multi or single -- hence for multi get subdomain -- and for single the localhost fallback! also: link includes applicationId so it opens the app detail page directly (not the list) ## QA multi workspace flag on - <img width="2996" height="1712" alt="CleanShot 2026-05-22 at 18 21 31@2x" src="https://github.com/user-attachments/assets/8499b9f3-b22e-45e2-8b97-4b27fadc3c94" /> multi workspace flag off - <img width="3012" height="1734" alt="CleanShot 2026-05-22 at 18 14 37@2x" src="https://github.com/user-attachments/assets/3af2f492-5e2d-4a4b-8251-c3343d79ae9e" />
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { ConfigService } from '@/cli/utilities/config/config-service';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import axios, { type AxiosInstance } from 'axios';
|
||||
import chalk from 'chalk';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export class ApiClient {
|
||||
readonly client: AxiosInstance;
|
||||
@@ -70,6 +72,74 @@ export class ApiClient {
|
||||
);
|
||||
}
|
||||
|
||||
async getFrontendUrl(): Promise<string | null> {
|
||||
try {
|
||||
const response = await this.client.get(
|
||||
'/.well-known/oauth-authorization-server',
|
||||
{ headers: { Accept: 'application/json' } },
|
||||
);
|
||||
const authorizationEndpoint = response.data?.authorization_endpoint;
|
||||
|
||||
if (!isNonEmptyString(authorizationEndpoint)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new URL(authorizationEndpoint).origin;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async getWorkspaceFrontendUrl(): Promise<string | null> {
|
||||
const workspaceFrontendUrl = await this.getCurrentWorkspaceFrontendUrl();
|
||||
|
||||
if (isDefined(workspaceFrontendUrl)) {
|
||||
return workspaceFrontendUrl;
|
||||
}
|
||||
|
||||
return this.getFrontendUrl();
|
||||
}
|
||||
|
||||
private async getCurrentWorkspaceFrontendUrl(): Promise<string | null> {
|
||||
try {
|
||||
const query = `
|
||||
query CurrentWorkspaceForFrontendUrl {
|
||||
currentWorkspace {
|
||||
workspaceUrls {
|
||||
subdomainUrl
|
||||
customUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const response = await this.client.post(
|
||||
'/metadata',
|
||||
{ query },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: '*/*',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const workspaceUrls =
|
||||
response.data?.data?.currentWorkspace?.workspaceUrls;
|
||||
const workspaceFrontendUrl = isNonEmptyString(workspaceUrls?.customUrl)
|
||||
? workspaceUrls.customUrl
|
||||
: workspaceUrls?.subdomainUrl;
|
||||
|
||||
if (!isNonEmptyString(workspaceFrontendUrl)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new URL(workspaceFrontendUrl).origin;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async validateAuth(): Promise<{ authValid: boolean; serverUp: boolean }> {
|
||||
try {
|
||||
const query = `
|
||||
|
||||
Reference in New Issue
Block a user