diff --git a/packages/twenty-docs/src/components/token-form.tsx b/packages/twenty-docs/src/components/token-form.tsx index b89216af7..8c9ee1fc1 100644 --- a/packages/twenty-docs/src/components/token-form.tsx +++ b/packages/twenty-docs/src/components/token-form.tsx @@ -48,10 +48,13 @@ const TokenForm = ({ await submitToken(event.target.value); }; - const updateBaseUrl = (baseUrl) => { - setBaseUrl(baseUrl); - submitBaseUrl?.(baseUrl); - localStorage.setItem('baseUrl', JSON.stringify({ baseUrl: baseUrl })); + const updateBaseUrl = (baseUrl: string) => { + const url = baseUrl?.endsWith('/') + ? baseUrl.substring(0, baseUrl.length - 1) + : baseUrl; + setBaseUrl(url); + submitBaseUrl?.(url); + localStorage.setItem('baseUrl', JSON.stringify({ baseUrl: url })); }; const validateToken = (openApiJson) => { diff --git a/packages/twenty-server/src/core/api-rest/api-rest.service.ts b/packages/twenty-server/src/core/api-rest/api-rest.service.ts index 086784bb2..ee41a7c14 100644 --- a/packages/twenty-server/src/core/api-rest/api-rest.service.ts +++ b/packages/twenty-server/src/core/api-rest/api-rest.service.ts @@ -22,9 +22,7 @@ export class ApiRestService { request: Request, data: ApiRestQuery, ): Promise { - const baseUrl = - this.environmentService.getServerUrl() || - `${request.protocol}://${request.get('host')}`; + const baseUrl = this.environmentService.getBaseUrl(request); try { return await this.httpService.axiosRef.post(`${baseUrl}/graphql`, data, { diff --git a/packages/twenty-server/src/core/api-rest/metadata-rest.service.ts b/packages/twenty-server/src/core/api-rest/metadata-rest.service.ts index 340889e61..e0df29aa8 100644 --- a/packages/twenty-server/src/core/api-rest/metadata-rest.service.ts +++ b/packages/twenty-server/src/core/api-rest/metadata-rest.service.ts @@ -18,9 +18,7 @@ export class ApiRestMetadataService { ) {} async callMetadata(request, data: ApiRestQuery) { - const baseUrl = - this.environmentService.getServerUrl() || - `${request.protocol}://${request.get('host')}`; + const baseUrl = this.environmentService.getBaseUrl(request); try { return await this.httpService.axiosRef.post(`${baseUrl}/metadata`, data, { diff --git a/packages/twenty-server/src/core/open-api/open-api.controller.ts b/packages/twenty-server/src/core/open-api/open-api.controller.ts index 2dcaf8a4b..b5617cb4c 100644 --- a/packages/twenty-server/src/core/open-api/open-api.controller.ts +++ b/packages/twenty-server/src/core/open-api/open-api.controller.ts @@ -23,7 +23,7 @@ export class OpenApiController { @Req() request: Request, @Res() res: Response, ) { - const data = await this.openApiService.generateMetaDataSchema(); + const data = await this.openApiService.generateMetaDataSchema(request); res.send(data); } diff --git a/packages/twenty-server/src/core/open-api/open-api.service.ts b/packages/twenty-server/src/core/open-api/open-api.service.ts index 80f4ee1ac..86cbcfded 100644 --- a/packages/twenty-server/src/core/open-api/open-api.service.ts +++ b/packages/twenty-server/src/core/open-api/open-api.service.ts @@ -25,16 +25,20 @@ import { getSingleResultSuccessResponse, } from 'src/core/open-api/utils/responses.utils'; import { getRequestBody } from 'src/core/open-api/utils/request-body.utils'; +import { EnvironmentService } from 'src/integrations/environment/environment.service'; @Injectable() export class OpenApiService { constructor( private readonly tokenService: TokenService, + private readonly environmentService: EnvironmentService, private readonly objectMetadataService: ObjectMetadataService, ) {} async generateCoreSchema(request: Request): Promise { - const schema = baseSchema('core'); + const baseUrl = this.environmentService.getBaseUrl(request); + + const schema = baseSchema('core', baseUrl); let objectMetadataItems; @@ -86,9 +90,12 @@ export class OpenApiService { return schema; } - async generateMetaDataSchema(): Promise { - //TODO Add once Rest MetaData api is ready - const schema = baseSchema('metadata'); + async generateMetaDataSchema( + request: Request, + ): Promise { + const baseUrl = this.environmentService.getBaseUrl(request); + + const schema = baseSchema('metadata', baseUrl); schema.tags = [{ name: 'placeholder' }]; diff --git a/packages/twenty-server/src/core/open-api/utils/base-schema.utils.ts b/packages/twenty-server/src/core/open-api/utils/base-schema.utils.ts index e7d969a7b..5d56dd818 100644 --- a/packages/twenty-server/src/core/open-api/utils/base-schema.utils.ts +++ b/packages/twenty-server/src/core/open-api/utils/base-schema.utils.ts @@ -4,6 +4,7 @@ import { computeOpenApiPath } from 'src/core/open-api/utils/path.utils'; export const baseSchema = ( schemaName: 'core' | 'metadata', + serverUrl: string, ): OpenAPIV3_1.Document => { return { openapi: '3.0.3', @@ -23,9 +24,7 @@ export const baseSchema = ( // Testing purposes servers: [ { - url: `https://api.twenty.com/rest/${ - schemaName !== 'core' ? schemaName : '' - }`, + url: `${serverUrl}/rest/${schemaName !== 'core' ? schemaName : ''}`, description: 'Production Development', }, ], @@ -49,6 +48,6 @@ export const baseSchema = ( description: 'Find out more about **Twenty**', url: 'https://twenty.com', }, - paths: { [`/open-api/${schemaName}`]: computeOpenApiPath() }, + paths: { [`/open-api/${schemaName}`]: computeOpenApiPath(serverUrl) }, }; }; diff --git a/packages/twenty-server/src/core/open-api/utils/path.utils.ts b/packages/twenty-server/src/core/open-api/utils/path.utils.ts index 67bbbf0b2..4a14640d1 100644 --- a/packages/twenty-server/src/core/open-api/utils/path.utils.ts +++ b/packages/twenty-server/src/core/open-api/utils/path.utils.ts @@ -95,7 +95,9 @@ export const computeSingleResultPath = ( } as OpenAPIV3_1.PathItemObject; }; -export const computeOpenApiPath = (): OpenAPIV3_1.PathItemObject => { +export const computeOpenApiPath = ( + serverUrl: string, +): OpenAPIV3_1.PathItemObject => { return { get: { tags: ['General'], @@ -103,7 +105,7 @@ export const computeOpenApiPath = (): OpenAPIV3_1.PathItemObject => { operationId: 'GetOpenApiSchema', servers: [ { - url: 'https://api.twenty.com/', + url: serverUrl, }, ], responses: { diff --git a/packages/twenty-server/src/integrations/environment/environment.service.ts b/packages/twenty-server/src/integrations/environment/environment.service.ts index 60604ae65..6b35c9bda 100644 --- a/packages/twenty-server/src/integrations/environment/environment.service.ts +++ b/packages/twenty-server/src/integrations/environment/environment.service.ts @@ -2,6 +2,8 @@ import { Injectable, LogLevel } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { Request } from 'express'; + import { EmailDriver } from 'src/integrations/email/interfaces/email.interface'; import { LoggerDriverType } from 'src/integrations/logger/interfaces'; @@ -86,7 +88,19 @@ export class EnvironmentService { } getServerUrl(): string { - return this.configService.get('SERVER_URL')!; + const url = this.configService.get('SERVER_URL')!; + + if (url?.endsWith('/')) { + return url.substring(0, url.length - 1); + } + + return url; + } + + getBaseUrl(request: Request): string { + return ( + this.getServerUrl() || `${request.protocol}://${request.get('host')}` + ); } getAccessTokenSecret(): string {