From bd3ec6d5e398813c771685f7593a1bf751a7aa94 Mon Sep 17 00:00:00 2001 From: nitin <142569587+ehconitin@users.noreply.github.com> Date: Wed, 9 Apr 2025 17:41:26 +0530 Subject: [PATCH] rename core-module environment to twenty-config (#11445) closes https://github.com/twentyhq/core-team-issues/issues/759 --- .../src/generated-metadata/graphql.ts | 153 +++-- .../twenty-front/src/generated/graphql.tsx | 122 ++-- .../components/SettingsAdminEnvVariables.tsx | 14 +- .../SettingsAdminEnvVariablesRow.tsx | 8 +- .../SettingsAdminEnvVariablesTable.tsx | 2 +- ...rouped.ts => getConfigVariablesGrouped.ts} | 8 +- .../SettingsAdminSecondaryEnvVariables.tsx | 18 +- .../twenty-server/jest-integration.config.ts | 2 +- .../__tests__/upgrade.command-runner.spec.ts | 26 +- .../command-runners/upgrade.command-runner.ts | 6 +- .../data-seed-demo-workspace.module.ts | 4 +- .../data-seed-demo-workspace.service.ts | 6 +- .../data-seed-dev-workspace.command.ts | 8 +- .../upgrade.command.ts | 6 +- .../src/database/typeorm/typeorm.module.ts | 4 +- .../src/database/typeorm/typeorm.service.ts | 18 +- .../graphql-config/graphql-config.service.ts | 12 +- .../graphql/metadata-graphql-api.module.ts | 8 +- .../api/graphql/metadata.module-factory.ts | 12 +- .../src/engine/api/rest/rest-api.service.ts | 12 +- .../admin-panel-health.service.spec.ts | 8 +- .../__tests__/admin-panel.service.spec.ts | 44 +- .../admin-panel/admin-panel.resolver.ts | 10 +- .../admin-panel/admin-panel.service.ts | 42 +- ...variable.dto.ts => config-variable.dto.ts} | 4 +- .../dtos/config-variables-group.dto.ts | 23 + .../dtos/config-variables.output.ts | 9 + .../dtos/environment-variables-group.dto.ts | 24 - .../dtos/environment-variables.output.ts | 9 - .../analytics/analytics.service.spec.ts | 4 +- .../analytics/analytics.service.ts | 6 +- .../approved-access-domain.service.ts | 10 +- .../services/approved-access-domain.spec.ts | 18 +- .../google-apis-auth.controller.ts | 6 +- .../microsoft-apis-auth.controller.ts | 6 +- .../enterprise-features-enabled.guard.ts | 6 +- ...pis-oauth-exchange-code-for-token.guard.ts | 10 +- .../google-apis-oauth-request-code.guard.ts | 14 +- .../guards/google-provider-enabled.guard.ts | 8 +- ...pis-oauth-exchange-code-for-token.guard.ts | 10 +- ...microsoft-apis-oauth-request-code.guard.ts | 14 +- .../microsoft-provider-enabled.guard.ts | 8 +- .../auth/services/api-key.service.spec.ts | 10 +- .../auth/services/api-key.service.ts | 4 +- .../auth/services/auth-sso.service.ts | 8 +- .../auth/services/auth-sso.spec.ts | 14 +- .../auth/services/auth.service.spec.ts | 10 +- .../auth/services/auth.service.ts | 16 +- .../auth/services/google-apis.service.ts | 10 +- .../auth/services/microsoft-apis.service.ts | 12 +- .../services/reset-password.service.spec.ts | 12 +- .../auth/services/reset-password.service.ts | 10 +- .../auth/services/sign-in-up.service.spec.ts | 18 +- .../auth/services/sign-in-up.service.ts | 10 +- .../google-apis-oauth-common.auth.strategy.ts | 10 +- ...h-exchange-code-for-token.auth.strategy.ts | 6 +- ...e-apis-oauth-request-code.auth.strategy.ts | 6 +- .../auth/strategies/google.auth.strategy.ts | 10 +- .../auth/strategies/jwt.auth.strategy.ts | 4 +- ...crosoft-apis-oauth-common.auth.strategy.ts | 10 +- ...h-exchange-code-for-token.auth.strategy.ts | 6 +- ...t-apis-oauth-request-code.auth.strategy.ts | 6 +- .../strategies/microsoft.auth.strategy.ts | 10 +- .../services/access-token.service.spec.ts | 14 +- .../token/services/access-token.service.ts | 8 +- .../email-verification-token.service.spec.ts | 10 +- .../email-verification-token.service.ts | 6 +- .../services/login-token.service.spec.ts | 12 +- .../token/services/login-token.service.ts | 6 +- .../services/refresh-token.service.spec.ts | 14 +- .../token/services/refresh-token.service.ts | 8 +- .../services/transient-token.service.spec.ts | 12 +- .../token/services/transient-token.service.ts | 6 +- .../billing-feature-used.listener.ts | 6 +- .../billing-workspace-member.listener.ts | 6 +- .../billing/services/billing-usage.service.ts | 6 +- .../billing/services/billing.service.ts | 6 +- .../stripe-billing-meter-event.service.ts | 8 +- .../services/stripe-billing-meter.service.ts | 8 +- .../services/stripe-billing-portal.service.ts | 8 +- .../services/stripe-checkout.service.ts | 10 +- .../services/stripe-customer.service.ts | 8 +- .../stripe/services/stripe-price.service.ts | 8 +- .../stripe/services/stripe-product.service.ts | 8 +- .../stripe-subscription-item.service.ts | 8 +- .../services/stripe-subscription.service.ts | 8 +- .../stripe/services/stripe-webhook.service.ts | 10 +- .../cache-storage.module-factory.ts | 8 +- .../cache-storage/cache-storage.module.ts | 4 +- .../captcha/captcha.module-factory.ts | 10 +- .../client-config.resolver.spec.ts | 4 +- .../client-config/client-config.resolver.ts | 65 +-- .../engine/core-modules/core-engine.module.ts | 24 +- .../controllers/cloudflare.spec.ts | 26 +- .../guards/cloudflare-secret.guard.ts | 6 +- .../guards/cloudflare-secret.spec.ts | 16 +- .../services/custom-domain.service.spec.ts | 30 +- .../services/custom-domain.service.ts | 18 +- .../services/domain-manager.service.spec.ts | 22 +- .../services/domain-manager.service.ts | 24 +- .../email-verification.module.ts | 4 +- .../services/email-verification.service.ts | 12 +- .../email/email.module-factory.ts | 16 +- ...vironment-variables-group-metadata.spec.ts | 28 - .../environment-variables-masking-config.ts | 29 - ...onment-variables-metadata-decorator-key.ts | 2 - ...-variables-metadata-decorator-names-key.ts | 2 - .../environment/environment.service.ts | 78 --- .../exception-handler.module-factory.ts | 18 +- .../file-storage.module-factory.ts | 20 +- .../file/file-upload/file-upload.module.ts | 4 +- .../resolvers/file-upload.resolver.spec.ts | 4 +- .../engine/core-modules/file/file.module.ts | 4 +- .../file/services/file.service.spec.ts | 6 +- .../file/services/file.service.ts | 6 +- .../generate-graphql-error-from-error.util.ts | 2 +- .../services/guard-redirect.service.ts | 10 +- .../src/engine/core-modules/jwt/jwt.module.ts | 14 +- .../jwt/services/jwt-wrapper.service.ts | 8 +- .../llm-chat-model.module-factory.ts | 6 +- .../llm-tracing/llm-tracing.module-factory.ts | 10 +- .../logger/logger.module-factory.ts | 12 +- .../message-queue.module-factory.ts | 8 +- .../metrics/metrics-cache.service.ts | 6 +- .../open-api/open-api.service.spec.ts | 4 +- .../core-modules/open-api/open-api.service.ts | 8 +- .../redis-client/redis-client.module.ts | 4 +- .../redis-client/redis-client.service.ts | 6 +- .../serverless/serverless-module.factory.ts | 16 +- .../session-storage.module-factory.ts | 10 +- .../sso/services/sso.service.spec.ts | 8 +- .../core-modules/sso/services/sso.service.ts | 12 +- .../telemetry/telemetry.service.ts | 6 +- .../config-variables.ts} | 530 +++++++++--------- .../config-variables-group-metadata.spec.ts | 28 + .../config-variables-group-metadata.ts} | 44 +- .../config-variables-masking-config.ts | 29 + ...config-variables-metadata-decorator-key.ts | 2 + ...-variables-metadata-decorator-names-key.ts | 2 + .../assert-or-warn.decorator.spec.ts | 18 +- .../cast-to-log-level-array.decorator.spec.ts | 2 +- .../cast-to-positive-number.decorator.spec.ts | 2 +- .../decorators/assert-or-warn.decorator.ts | 0 .../decorators/cast-to-boolean.decorator.ts | 0 .../cast-to-log-level-array.decorator.ts | 0 .../cast-to-meter-driver.decorator.ts | 0 .../cast-to-positive-number.decorator.ts | 0 .../cast-to-string-array.decorator.ts | 0 .../config-variables-metadata.decorator.ts} | 23 +- .../decorators/is-aws-region.decorator.ts | 0 .../decorators/is-duration.decorator.ts | 0 .../is-optional-or-empty-string.decorator.ts | 0 .../is-strictly-lower-than.decorator.ts | 0 .../decorators/is-twenty-semver.decorator.ts | 0 .../enums/config-variables-group.enum.ts} | 2 +- ...nfig-variables-masking-strategies.enum.ts} | 2 +- .../environment.service.spec.ts | 30 +- .../interfaces/aws-region.interface.ts | 0 .../interfaces/node-environment.interface.ts | 0 .../interfaces/support.interface.ts | 0 .../twenty-config.module-definition.ts} | 2 +- .../twenty-config.module.ts} | 12 +- .../twenty-config/twenty-config.service.ts | 73 +++ ...variable-mask-sensitive-data.util.spec.ts} | 46 +- ...nfig-variable-mask-sensitive-data.util.ts} | 12 +- .../engine/core-modules/user/user.resolver.ts | 12 +- .../workspace-invitation.service.spec.ts | 14 +- .../services/workspace-invitation.service.ts | 10 +- .../__tests__/workspace.service.spec.ts | 4 +- .../workspace/services/workspace.service.ts | 14 +- .../workspace/workspace.resolver.ts | 22 +- .../serverless-function.service.ts | 10 +- .../factories/workspace-datasource.factory.ts | 12 +- .../utils/global-exception-handler.util.ts | 2 +- .../services/cleaner.workspace-service.ts | 25 +- packages/twenty-server/src/instrument.ts | 2 +- packages/twenty-server/src/main.ts | 10 +- .../google-calendar-driver.module.ts | 4 +- .../microsoft-calendar-driver.module.ts | 4 +- .../google-oauth2-client-manager.service.ts | 8 +- ...microsoft-oauth2-client-manager.service.ts | 8 +- ...google-api-refresh-access-token.service.ts | 10 +- ...crosoft-api-refresh-access-token.module.ts | 4 +- .../microsoft-api-refresh-tokens.service.ts | 8 +- .../gmail/messaging-gmail-driver.module.ts | 4 +- .../messaging-microsoft-driver.module.ts | 4 +- ...osoft-get-message-list.service.dev.spec.ts | 8 +- ...microsoft-get-messages.service.dev.spec.ts | 4 +- .../microsoft-get-messages.service.spec.ts | 4 +- .../services/messaging-telemetry.service.ts | 4 +- .../workflow-runner/jobs/run-workflow.job.ts | 8 +- .../twenty-server/src/utils/typed-reflect.ts | 4 +- packages/twenty-utils/dangerfile.ts | 6 +- 193 files changed, 1454 insertions(+), 1422 deletions(-) rename packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/{getEnvironmentVariablesGrouped.ts => getConfigVariablesGrouped.ts} (58%) rename packages/twenty-server/src/engine/core-modules/admin-panel/dtos/{environment-variable.dto.ts => config-variable.dto.ts} (75%) create mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts create mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/environment/environment.service.ts rename packages/twenty-server/src/engine/core-modules/{environment/environment-variables.ts => twenty-config/config-variables.ts} (63%) create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts rename packages/twenty-server/src/engine/core-modules/{environment/constants/environment-variables-group-metadata.ts => twenty-config/constants/config-variables-group-metadata.ts} (77%) create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/__tests__/assert-or-warn.decorator.spec.ts (81%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts (93%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/__tests__/cast-to-positive-number.decorator.spec.ts (92%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/assert-or-warn.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-boolean.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-log-level-array.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-meter-driver.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-positive-number.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/cast-to-string-array.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment/decorators/environment-variables-metadata.decorator.ts => twenty-config/decorators/config-variables-metadata.decorator.ts} (58%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-aws-region.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-duration.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-optional-or-empty-string.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-strictly-lower-than.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/decorators/is-twenty-semver.decorator.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment/enums/environment-variables-group.enum.ts => twenty-config/enums/config-variables-group.enum.ts} (93%) rename packages/twenty-server/src/engine/core-modules/{environment/enums/environment-variables-masking-strategies.enum.ts => twenty-config/enums/config-variables-masking-strategies.enum.ts} (57%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/environment.service.spec.ts (65%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/interfaces/aws-region.interface.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/interfaces/node-environment.interface.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment => twenty-config}/interfaces/support.interface.ts (100%) rename packages/twenty-server/src/engine/core-modules/{environment/environment.module-definition.ts => twenty-config/twenty-config.module-definition.ts} (86%) rename packages/twenty-server/src/engine/core-modules/{environment/environment.module.ts => twenty-config/twenty-config.module.ts} (50%) create mode 100644 packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts rename packages/twenty-server/src/engine/core-modules/{environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts => twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts} (53%) rename packages/twenty-server/src/engine/core-modules/{environment/utils/environment-variable-mask-sensitive-data.util.ts => twenty-config/utils/config-variable-mask-sensitive-data.util.ts} (56%) diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index dedafd5f4ec..d71c26ea2cf 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -145,6 +145,25 @@ export type Billing = { trialPeriods: Array; }; +export type BillingEndTrialPeriodOutput = { + __typename?: 'BillingEndTrialPeriodOutput'; + /** Boolean that confirms if a payment method was found */ + hasPaymentMethod: Scalars['Boolean']['output']; + /** Updated subscription status */ + status?: Maybe; +}; + +export type BillingMeteredProductUsageOutput = { + __typename?: 'BillingMeteredProductUsageOutput'; + includedFreeQuantity: Scalars['Float']['output']; + periodEnd: Scalars['DateTime']['output']; + periodStart: Scalars['DateTime']['output']; + productKey: BillingProductKey; + totalCostCents: Scalars['Float']['output']; + unitPriceCents: Scalars['Float']['output']; + usageQuantity: Scalars['Float']['output']; +}; + /** The different billing plans available */ export enum BillingPlanKey { ENTERPRISE = 'ENTERPRISE', @@ -153,9 +172,9 @@ export enum BillingPlanKey { export type BillingPlanOutput = { __typename?: 'BillingPlanOutput'; - baseProduct: BillingProductDto; - meteredProducts: Array; - otherLicensedProducts: Array; + baseProduct: BillingProduct; + meteredProducts: Array; + otherLicensedProducts: Array; planKey: BillingPlanKey; }; @@ -191,13 +210,26 @@ export enum BillingPriceTiersMode { export type BillingPriceUnionDto = BillingPriceLicensedDto | BillingPriceMeteredDto; -export type BillingProductDto = { - __typename?: 'BillingProductDTO'; +export type BillingProduct = { + __typename?: 'BillingProduct'; description: Scalars['String']['output']; images?: Maybe>; + metadata: BillingProductMetadata; name: Scalars['String']['output']; - prices: Array; - type: BillingUsageType; + prices?: Maybe>; +}; + +/** The different billing products available */ +export enum BillingProductKey { + BASE_PRODUCT = 'BASE_PRODUCT', + WORKFLOW_NODE_EXECUTION = 'WORKFLOW_NODE_EXECUTION' +} + +export type BillingProductMetadata = { + __typename?: 'BillingProductMetadata'; + planKey: BillingPlanKey; + priceUsageBased: BillingUsageType; + productKey: BillingProductKey; }; export type BillingSessionOutput = { @@ -207,11 +239,19 @@ export type BillingSessionOutput = { export type BillingSubscription = { __typename?: 'BillingSubscription'; + billingSubscriptionItems?: Maybe>; id: Scalars['UUID']['output']; interval?: Maybe; status: SubscriptionStatus; }; +export type BillingSubscriptionItem = { + __typename?: 'BillingSubscriptionItem'; + billingProduct?: Maybe; + hasReachedCurrentPeriodCap: Scalars['Boolean']['output']; + id: Scalars['UUID']['output']; +}; + export type BillingTrialPeriodDto = { __typename?: 'BillingTrialPeriodDTO'; duration: Scalars['Float']['output']; @@ -280,6 +320,49 @@ export type ComputeStepOutputSchemaInput = { step: Scalars['JSON']['input']; }; +export type ConfigVariable = { + __typename?: 'ConfigVariable'; + description: Scalars['String']['output']; + isSensitive: Scalars['Boolean']['output']; + name: Scalars['String']['output']; + value: Scalars['String']['output']; +}; + +export enum ConfigVariablesGroup { + AnalyticsConfig = 'AnalyticsConfig', + BillingConfig = 'BillingConfig', + CaptchaConfig = 'CaptchaConfig', + CloudflareConfig = 'CloudflareConfig', + EmailSettings = 'EmailSettings', + ExceptionHandler = 'ExceptionHandler', + GoogleAuth = 'GoogleAuth', + LLM = 'LLM', + Logging = 'Logging', + Metering = 'Metering', + MicrosoftAuth = 'MicrosoftAuth', + Other = 'Other', + RateLimiting = 'RateLimiting', + SSL = 'SSL', + ServerConfig = 'ServerConfig', + ServerlessConfig = 'ServerlessConfig', + StorageConfig = 'StorageConfig', + SupportChatConfig = 'SupportChatConfig', + TokensDuration = 'TokensDuration' +} + +export type ConfigVariablesGroupData = { + __typename?: 'ConfigVariablesGroupData'; + description: Scalars['String']['output']; + isHiddenOnLoad: Scalars['Boolean']['output']; + name: ConfigVariablesGroup; + variables: Array; +}; + +export type ConfigVariablesOutput = { + __typename?: 'ConfigVariablesOutput'; + groups: Array; +}; + export type CreateAppTokenInput = { expiresAt: Scalars['DateTime']['input']; }; @@ -498,49 +581,6 @@ export type EmailPasswordResetLink = { success: Scalars['Boolean']['output']; }; -export type EnvironmentVariable = { - __typename?: 'EnvironmentVariable'; - description: Scalars['String']['output']; - name: Scalars['String']['output']; - sensitive: Scalars['Boolean']['output']; - value: Scalars['String']['output']; -}; - -export enum EnvironmentVariablesGroup { - AnalyticsConfig = 'AnalyticsConfig', - BillingConfig = 'BillingConfig', - CaptchaConfig = 'CaptchaConfig', - CloudflareConfig = 'CloudflareConfig', - EmailSettings = 'EmailSettings', - ExceptionHandler = 'ExceptionHandler', - GoogleAuth = 'GoogleAuth', - LLM = 'LLM', - Logging = 'Logging', - Metering = 'Metering', - MicrosoftAuth = 'MicrosoftAuth', - Other = 'Other', - RateLimiting = 'RateLimiting', - SSL = 'SSL', - ServerConfig = 'ServerConfig', - ServerlessConfig = 'ServerlessConfig', - StorageConfig = 'StorageConfig', - SupportChatConfig = 'SupportChatConfig', - TokensDuration = 'TokensDuration' -} - -export type EnvironmentVariablesGroupData = { - __typename?: 'EnvironmentVariablesGroupData'; - description: Scalars['String']['output']; - isHiddenOnLoad: Scalars['Boolean']['output']; - name: EnvironmentVariablesGroup; - variables: Array; -}; - -export type EnvironmentVariablesOutput = { - __typename?: 'EnvironmentVariablesOutput'; - groups: Array; -}; - export type ExecuteServerlessFunctionInput = { /** Id of the serverless function to execute */ id: Scalars['UUID']['input']; @@ -908,6 +948,7 @@ export type Mutation = { editSSOIdentityProvider: EditSsoOutput; emailPasswordResetLink: EmailPasswordResetLink; enablePostgresProxy: PostgresCredentials; + endSubscriptionTrialPeriod: BillingEndTrialPeriodOutput; executeOneServerlessFunction: ServerlessFunctionExecutionResult; generateApiKeyToken: ApiKeyToken; generateTransientToken: TransientToken; @@ -926,11 +967,11 @@ export type Mutation = { signUpInNewWorkspace: SignUpOutput; skipSyncEmailOnboardingStep: OnboardingStepSuccess; submitFormStep: Scalars['Boolean']['output']; + switchToYearlyInterval: BillingUpdateOutput; syncRemoteTable: RemoteTable; syncRemoteTableSchemaChanges: RemoteTable; track: Analytics; unsyncRemoteTable: RemoteTable; - updateBillingSubscription: BillingUpdateOutput; updateLabPublicFeatureFlag: FeatureFlag; updateOneField: Field; updateOneObject: Object; @@ -1524,8 +1565,9 @@ export type Query = { findWorkspaceInvitations: Array; getApprovedAccessDomains: Array; getAvailablePackages: Scalars['JSON']['output']; - getEnvironmentVariablesGrouped: EnvironmentVariablesOutput; + getConfigVariablesGrouped: ConfigVariablesOutput; getIndicatorHealthStatus: AdminPanelHealthServiceData; + getMeteredProductsUsage: Array; getPostgresCredentials?: Maybe; getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput; getQueueMetrics: QueueMetricsData; @@ -1545,6 +1587,7 @@ export type Query = { relationMetadata: RelationMetadataConnection; search: Array; validatePasswordResetToken: ValidatePasswordResetToken; + versionInfo: VersionInfo; }; @@ -2369,6 +2412,12 @@ export type ValidatePasswordResetToken = { id: Scalars['String']['output']; }; +export type VersionInfo = { + __typename?: 'VersionInfo'; + currentVersion?: Maybe; + latestVersion: Scalars['String']['output']; +}; + export type WorkerQueueMetrics = { __typename?: 'WorkerQueueMetrics'; active: Scalars['Float']['output']; diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 878e7002be1..3379f8e18c5 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -312,6 +312,49 @@ export type ComputeStepOutputSchemaInput = { step: Scalars['JSON']; }; +export type ConfigVariable = { + __typename?: 'ConfigVariable'; + description: Scalars['String']; + isSensitive: Scalars['Boolean']; + name: Scalars['String']; + value: Scalars['String']; +}; + +export enum ConfigVariablesGroup { + AnalyticsConfig = 'AnalyticsConfig', + BillingConfig = 'BillingConfig', + CaptchaConfig = 'CaptchaConfig', + CloudflareConfig = 'CloudflareConfig', + EmailSettings = 'EmailSettings', + ExceptionHandler = 'ExceptionHandler', + GoogleAuth = 'GoogleAuth', + LLM = 'LLM', + Logging = 'Logging', + Metering = 'Metering', + MicrosoftAuth = 'MicrosoftAuth', + Other = 'Other', + RateLimiting = 'RateLimiting', + SSL = 'SSL', + ServerConfig = 'ServerConfig', + ServerlessConfig = 'ServerlessConfig', + StorageConfig = 'StorageConfig', + SupportChatConfig = 'SupportChatConfig', + TokensDuration = 'TokensDuration' +} + +export type ConfigVariablesGroupData = { + __typename?: 'ConfigVariablesGroupData'; + description: Scalars['String']; + isHiddenOnLoad: Scalars['Boolean']; + name: ConfigVariablesGroup; + variables: Array; +}; + +export type ConfigVariablesOutput = { + __typename?: 'ConfigVariablesOutput'; + groups: Array; +}; + export type CreateApprovedAccessDomainInput = { domain: Scalars['String']; email: Scalars['String']; @@ -469,49 +512,6 @@ export type EmailPasswordResetLink = { success: Scalars['Boolean']; }; -export type EnvironmentVariable = { - __typename?: 'EnvironmentVariable'; - description: Scalars['String']; - name: Scalars['String']; - sensitive: Scalars['Boolean']; - value: Scalars['String']; -}; - -export enum EnvironmentVariablesGroup { - AnalyticsConfig = 'AnalyticsConfig', - BillingConfig = 'BillingConfig', - CaptchaConfig = 'CaptchaConfig', - CloudflareConfig = 'CloudflareConfig', - EmailSettings = 'EmailSettings', - ExceptionHandler = 'ExceptionHandler', - GoogleAuth = 'GoogleAuth', - LLM = 'LLM', - Logging = 'Logging', - Metering = 'Metering', - MicrosoftAuth = 'MicrosoftAuth', - Other = 'Other', - RateLimiting = 'RateLimiting', - SSL = 'SSL', - ServerConfig = 'ServerConfig', - ServerlessConfig = 'ServerlessConfig', - StorageConfig = 'StorageConfig', - SupportChatConfig = 'SupportChatConfig', - TokensDuration = 'TokensDuration' -} - -export type EnvironmentVariablesGroupData = { - __typename?: 'EnvironmentVariablesGroupData'; - description: Scalars['String']; - isHiddenOnLoad: Scalars['Boolean']; - name: EnvironmentVariablesGroup; - variables: Array; -}; - -export type EnvironmentVariablesOutput = { - __typename?: 'EnvironmentVariablesOutput'; - groups: Array; -}; - export type ExecuteServerlessFunctionInput = { /** Id of the serverless function to execute */ id: Scalars['UUID']; @@ -1428,7 +1428,7 @@ export type Query = { findWorkspaceInvitations: Array; getApprovedAccessDomains: Array; getAvailablePackages: Scalars['JSON']; - getEnvironmentVariablesGrouped: EnvironmentVariablesOutput; + getConfigVariablesGrouped: ConfigVariablesOutput; getIndicatorHealthStatus: AdminPanelHealthServiceData; getMeteredProductsUsage: Array; getPostgresCredentials?: Maybe; @@ -2625,10 +2625,10 @@ export type UserLookupAdminPanelMutationVariables = Exact<{ export type UserLookupAdminPanelMutation = { __typename?: 'Mutation', userLookupAdminPanel: { __typename?: 'UserLookup', user: { __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }, workspaces: Array<{ __typename?: 'WorkspaceInfo', id: string, name: string, logo?: string | null, totalUsers: number, allowImpersonation: boolean, users: Array<{ __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }>, featureFlags: Array<{ __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean }> }> } }; -export type GetEnvironmentVariablesGroupedQueryVariables = Exact<{ [key: string]: never; }>; +export type GetConfigVariablesGroupedQueryVariables = Exact<{ [key: string]: never; }>; -export type GetEnvironmentVariablesGroupedQuery = { __typename?: 'Query', getEnvironmentVariablesGrouped: { __typename?: 'EnvironmentVariablesOutput', groups: Array<{ __typename?: 'EnvironmentVariablesGroupData', name: EnvironmentVariablesGroup, description: string, isHiddenOnLoad: boolean, variables: Array<{ __typename?: 'EnvironmentVariable', name: string, description: string, value: string, sensitive: boolean }> }> } }; +export type GetConfigVariablesGroupedQuery = { __typename?: 'Query', getConfigVariablesGrouped: { __typename?: 'ConfigVariablesOutput', groups: Array<{ __typename?: 'ConfigVariablesGroupData', name: ConfigVariablesGroup, description: string, isHiddenOnLoad: boolean, variables: Array<{ __typename?: 'ConfigVariable', name: string, description: string, value: string, isSensitive: boolean }> }> } }; export type GetVersionInfoQueryVariables = Exact<{ [key: string]: never; }>; @@ -4578,9 +4578,9 @@ export function useUserLookupAdminPanelMutation(baseOptions?: Apollo.MutationHoo export type UserLookupAdminPanelMutationHookResult = ReturnType; export type UserLookupAdminPanelMutationResult = Apollo.MutationResult; export type UserLookupAdminPanelMutationOptions = Apollo.BaseMutationOptions; -export const GetEnvironmentVariablesGroupedDocument = gql` - query GetEnvironmentVariablesGrouped { - getEnvironmentVariablesGrouped { +export const GetConfigVariablesGroupedDocument = gql` + query GetConfigVariablesGrouped { + getConfigVariablesGrouped { groups { name description @@ -4589,7 +4589,7 @@ export const GetEnvironmentVariablesGroupedDocument = gql` name description value - sensitive + isSensitive } } } @@ -4597,31 +4597,31 @@ export const GetEnvironmentVariablesGroupedDocument = gql` `; /** - * __useGetEnvironmentVariablesGroupedQuery__ + * __useGetConfigVariablesGroupedQuery__ * - * To run a query within a React component, call `useGetEnvironmentVariablesGroupedQuery` and pass it any options that fit your needs. - * When your component renders, `useGetEnvironmentVariablesGroupedQuery` returns an object from Apollo Client that contains loading, error, and data properties + * To run a query within a React component, call `useGetConfigVariablesGroupedQuery` and pass it any options that fit your needs. + * When your component renders, `useGetConfigVariablesGroupedQuery` returns an object from Apollo Client that contains loading, error, and data properties * you can use to render your UI. * * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; * * @example - * const { data, loading, error } = useGetEnvironmentVariablesGroupedQuery({ + * const { data, loading, error } = useGetConfigVariablesGroupedQuery({ * variables: { * }, * }); */ -export function useGetEnvironmentVariablesGroupedQuery(baseOptions?: Apollo.QueryHookOptions) { +export function useGetConfigVariablesGroupedQuery(baseOptions?: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetEnvironmentVariablesGroupedDocument, options); + return Apollo.useQuery(GetConfigVariablesGroupedDocument, options); } -export function useGetEnvironmentVariablesGroupedLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { +export function useGetConfigVariablesGroupedLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetEnvironmentVariablesGroupedDocument, options); + return Apollo.useLazyQuery(GetConfigVariablesGroupedDocument, options); } -export type GetEnvironmentVariablesGroupedQueryHookResult = ReturnType; -export type GetEnvironmentVariablesGroupedLazyQueryHookResult = ReturnType; -export type GetEnvironmentVariablesGroupedQueryResult = Apollo.QueryResult; +export type GetConfigVariablesGroupedQueryHookResult = ReturnType; +export type GetConfigVariablesGroupedLazyQueryHookResult = ReturnType; +export type GetConfigVariablesGroupedQueryResult = Apollo.QueryResult; export const GetVersionInfoDocument = gql` query GetVersionInfo { versionInfo { diff --git a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx index 893ebf5efc3..7aed808d175 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariables.tsx @@ -5,10 +5,10 @@ import { SettingsPath } from '@/types/SettingsPath'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { t } from '@lingui/core/macro'; -import { useGetEnvironmentVariablesGroupedQuery } from '~/generated/graphql'; -import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; -import { Card, Section } from 'twenty-ui/layout'; import { H2Title, IconHeartRateMonitor } from 'twenty-ui/display'; +import { Card, Section } from 'twenty-ui/layout'; +import { useGetConfigVariablesGroupedQuery } from '~/generated/graphql'; +import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; const StyledGroupContainer = styled.div``; @@ -22,17 +22,17 @@ const StyledCard = styled(Card)` export const SettingsAdminEnvVariables = () => { const theme = useTheme(); - const { data: environmentVariables, loading: environmentVariablesLoading } = - useGetEnvironmentVariablesGroupedQuery({ + const { data: configVariables, loading: configVariablesLoading } = + useGetConfigVariablesGroupedQuery({ fetchPolicy: 'network-only', }); const visibleGroups = - environmentVariables?.getEnvironmentVariablesGrouped.groups.filter( + configVariables?.getConfigVariablesGrouped.groups.filter( (group) => !group.isHiddenOnLoad, ) ?? []; - if (environmentVariablesLoading) { + if (configVariablesLoading) { return ; } diff --git a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx index 94a57549798..27ecee16385 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminEnvVariablesRow.tsx @@ -6,16 +6,16 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; import { useState } from 'react'; -import { AnimatedExpandableContainer } from 'twenty-ui/layout'; import { IconChevronRight, IconEye, IconEyeOff } from 'twenty-ui/display'; import { LightIconButton } from 'twenty-ui/input'; +import { AnimatedExpandableContainer } from 'twenty-ui/layout'; type SettingsAdminEnvVariablesRowProps = { variable: { name: string; description: string; value: string; - sensitive: boolean; + isSensitive: boolean; }; isExpanded: boolean; onExpandToggle: (name: string) => void; @@ -79,7 +79,7 @@ export const SettingsAdminEnvVariablesRow = ({ const displayValue = variable.value === '' ? 'null' - : variable.sensitive && !showSensitiveValue + : variable.isSensitive && !showSensitiveValue ? '••••••' : variable.value; @@ -112,7 +112,7 @@ export const SettingsAdminEnvVariablesRow = ({ displayText={displayValue} multiline={true} /> - {variable.sensitive && variable.value !== '' && ( + {variable.isSensitive && variable.value !== '' && ( ; }; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getEnvironmentVariablesGrouped.ts b/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getConfigVariablesGrouped.ts similarity index 58% rename from packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getEnvironmentVariablesGrouped.ts rename to packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getConfigVariablesGrouped.ts index 7c8f94c25ee..32996402521 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getEnvironmentVariablesGrouped.ts +++ b/packages/twenty-front/src/modules/settings/admin-panel/graphql/queries/getConfigVariablesGrouped.ts @@ -1,8 +1,8 @@ import { gql } from '@apollo/client'; -export const GET_ENVIRONMENT_VARIABLES_GROUPED = gql` - query GetEnvironmentVariablesGrouped { - getEnvironmentVariablesGrouped { +export const GET_CONFIG_VARIABLES_GROUPED = gql` + query GetConfigVariablesGrouped { + getConfigVariablesGrouped { groups { name description @@ -11,7 +11,7 @@ export const GET_ENVIRONMENT_VARIABLES_GROUPED = gql` name description value - sensitive + isSensitive } } } diff --git a/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx b/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx index 735e95f6997..ce89803ad5c 100644 --- a/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx +++ b/packages/twenty-front/src/pages/settings/admin-panel/SettingsAdminSecondaryEnvVariables.tsx @@ -5,24 +5,26 @@ import { SettingsPath } from '@/types/SettingsPath'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; import styled from '@emotion/styled'; import { t } from '@lingui/core/macro'; -import { useGetEnvironmentVariablesGroupedQuery } from '~/generated/graphql'; -import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; import { H2Title } from 'twenty-ui/display'; +import { useGetConfigVariablesGroupedQuery } from '~/generated/graphql'; +import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; const StyledGroupContainer = styled.div``; export const SettingsAdminSecondaryEnvVariables = () => { - const { data: environmentVariables, loading: environmentVariablesLoading } = - useGetEnvironmentVariablesGroupedQuery({ - fetchPolicy: 'network-only', - }); + const { + data: secondaryConfigVariables, + loading: secondaryConfigVariablesLoading, + } = useGetConfigVariablesGroupedQuery({ + fetchPolicy: 'network-only', + }); const hiddenGroups = - environmentVariables?.getEnvironmentVariablesGrouped.groups.filter( + secondaryConfigVariables?.getConfigVariablesGrouped.groups.filter( (group) => group.isHiddenOnLoad, ) ?? []; - if (environmentVariablesLoading) { + if (secondaryConfigVariablesLoading) { return ; } diff --git a/packages/twenty-server/jest-integration.config.ts b/packages/twenty-server/jest-integration.config.ts index 332e243bff9..05b499db568 100644 --- a/packages/twenty-server/jest-integration.config.ts +++ b/packages/twenty-server/jest-integration.config.ts @@ -1,6 +1,6 @@ import { JestConfigWithTsJest, pathsToModuleNameMapper } from 'ts-jest'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; const isBillingEnabled = process.env.IS_BILLING_ENABLED === 'true'; diff --git a/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts b/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts index 82f7854a9f8..e3313adcdf7 100644 --- a/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts +++ b/packages/twenty-server/src/database/commands/command-runners/__tests__/upgrade.command-runner.spec.ts @@ -6,8 +6,8 @@ import { EachTestingContext } from 'twenty-shared/testing'; import { Repository } from 'typeorm'; import { UpgradeCommandRunner } from 'src/database/commands/command-runners/upgrade.command-runner'; -import { EnvironmentVariables } from 'src/engine/core-modules/environment/environment-variables'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; @@ -97,20 +97,18 @@ const buildUpgradeCommandModule = async ({ }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { - get: jest - .fn() - .mockImplementation((key: keyof EnvironmentVariables) => { - switch (key) { - case 'APP_VERSION': { - return appVersion; - } - default: { - return; - } + get: jest.fn().mockImplementation((key: keyof ConfigVariables) => { + switch (key) { + case 'APP_VERSION': { + return appVersion; } - }), + default: { + return; + } + } + }), }, }, { diff --git a/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts b/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts index e322284b35f..2ae7d26bbdf 100644 --- a/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts +++ b/packages/twenty-server/src/database/commands/command-runners/upgrade.command-runner.ts @@ -9,7 +9,7 @@ import { ActiveOrSuspendedWorkspacesMigrationCommandRunner, RunOnWorkspaceArgs, } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; @@ -26,7 +26,7 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi constructor( @InjectRepository(Workspace, 'core') protected readonly workspaceRepository: Repository, - protected readonly environmentService: EnvironmentService, + protected readonly twentyConfigService: TwentyConfigService, protected readonly twentyORMGlobalManager: TwentyORMGlobalManager, protected readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand, ) { @@ -87,7 +87,7 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi } private retrieveToVersionFromAppVersion() { - const appVersion = this.environmentService.get('APP_VERSION'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); if (!isDefined(appVersion)) { throw new Error( diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts index d3ce4a65fa4..e1336ff5d9a 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module.ts @@ -2,14 +2,14 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { DataSeedDemoWorkspaceService } from 'src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module'; @Module({ imports: [ WorkspaceManagerModule, - EnvironmentModule, + TwentyConfigModule, TypeOrmModule.forFeature([Workspace], 'core'), ], providers: [DataSeedDemoWorkspaceService], diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts index d7be191c324..0ca70c13f41 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts @@ -9,7 +9,7 @@ import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; @@ -21,7 +21,7 @@ export class DataSeedDemoWorkspaceService { protected readonly workspaceRepository: Repository, @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) private readonly workspaceSchemaCache: CacheStorageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async seedDemo(): Promise { @@ -43,7 +43,7 @@ export class DataSeedDemoWorkspaceService { await deleteCoreSchema(rawDataSource, workspaceId); } - const appVersion = this.environmentService.get('APP_VERSION'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); await seedCoreSchema({ workspaceDataSource: rawDataSource, diff --git a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts index 7d0cf6c284e..b3832fadba6 100644 --- a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts @@ -32,7 +32,7 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; @@ -68,7 +68,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner { private readonly workspaceSchemaCache: CacheStorageService, private readonly seederService: SeederService, private readonly workspaceManagerService: WorkspaceManagerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { super(); } @@ -94,8 +94,8 @@ export class DataSeedWorkspaceCommand extends CommandRunner { await rawDataSource.initialize(); - const isBillingEnabled = this.environmentService.get('IS_BILLING_ENABLED'); - const appVersion = this.environmentService.get('APP_VERSION'); + const isBillingEnabled = this.twentyConfigService.get('IS_BILLING_ENABLED'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); await seedCoreSchema({ workspaceDataSource: rawDataSource, diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts index b0ef99dde2c..c247d00cca2 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts @@ -17,7 +17,7 @@ import { UpdateDefaultViewRecordOpeningOnWorkflowObjectsCommand } from 'src/data import { InitializePermissionsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-initialize-permissions.command'; import { UpdateViewAggregateOperationsCommand } from 'src/database/commands/upgrade-version-command/0-44/0-44-update-view-aggregate-operations.command'; import { UpgradeCreatedByEnumCommand } from 'src/database/commands/upgrade-version-command/0-51/0-51-update-workflow-trigger-type-enum.command'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command'; @@ -37,7 +37,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { constructor( @InjectRepository(Workspace, 'core') protected readonly workspaceRepository: Repository, - protected readonly environmentService: EnvironmentService, + protected readonly twentyConfigService: TwentyConfigService, protected readonly twentyORMGlobalManager: TwentyORMGlobalManager, protected readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand, @@ -57,7 +57,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { ) { super( workspaceRepository, - environmentService, + twentyConfigService, twentyORMGlobalManager, syncWorkspaceMetadataCommand, ); diff --git a/packages/twenty-server/src/database/typeorm/typeorm.module.ts b/packages/twenty-server/src/database/typeorm/typeorm.module.ts index 15733f0c632..88a9b26e390 100644 --- a/packages/twenty-server/src/database/typeorm/typeorm.module.ts +++ b/packages/twenty-server/src/database/typeorm/typeorm.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; import { typeORMCoreModuleOptions } from 'src/database/typeorm/core/core.datasource'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { TypeORMService } from './typeorm.service'; @@ -28,7 +28,7 @@ const coreTypeORMFactory = async (): Promise => ({ useFactory: coreTypeORMFactory, name: 'core', }), - EnvironmentModule, + TwentyConfigModule, ], providers: [TypeORMService], exports: [TypeORMService], diff --git a/packages/twenty-server/src/database/typeorm/typeorm.service.ts b/packages/twenty-server/src/database/typeorm/typeorm.service.ts index f1fe7e0ae13..dcf12bc2767 100644 --- a/packages/twenty-server/src/database/typeorm/typeorm.service.ts +++ b/packages/twenty-server/src/database/typeorm/typeorm.service.ts @@ -2,7 +2,7 @@ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { ApprovedAccessDomain } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.entity'; @@ -13,11 +13,11 @@ import { BillingPrice } from 'src/engine/core-modules/billing/entities/billing-p import { BillingProduct } from 'src/engine/core-modules/billing/entities/billing-product.entity'; import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity'; import { PostgresCredentials } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.entity'; import { WorkspaceSSOIdentityProvider } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { TwoFactorMethod } from 'src/engine/core-modules/two-factor-method/two-factor-method.entity'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -29,12 +29,12 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy { private dataSources: Map = new Map(); private isDatasourceInitializing: Map = new Map(); - constructor(private readonly environmentService: EnvironmentService) { + constructor(private readonly twentyConfigService: TwentyConfigService) { this.mainDataSource = new DataSource({ - url: environmentService.get('PG_DATABASE_URL'), + url: twentyConfigService.get('PG_DATABASE_URL'), type: 'postgres', logging: - environmentService.get('NODE_ENV') === NodeEnvironment.development + twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? ['query', 'error'] : ['error'], schema: 'core', @@ -58,7 +58,7 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy { TwoFactorMethod, ], metadataTableName: '_typeorm_generated_columns_and_materialized_views', - ssl: environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') + ssl: twentyConfigService.get('PG_SSL_ALLOW_SELF_SIGNED') ? { rejectUnauthorized: false, } @@ -111,14 +111,14 @@ export class TypeORMService implements OnModuleInit, OnModuleDestroy { const schema = dataSource.schema; const workspaceDataSource = new DataSource({ - url: dataSource.url ?? this.environmentService.get('PG_DATABASE_URL'), + url: dataSource.url ?? this.twentyConfigService.get('PG_DATABASE_URL'), type: 'postgres', logging: - this.environmentService.get('NODE_ENV') === NodeEnvironment.development + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? ['query', 'error'] : ['error'], schema, - ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') + ssl: this.twentyConfigService.get('PG_SSL_ALLOW_SELF_SIGNED') ? { rejectUnauthorized: false, } diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts index 6e859356174..72e5f775766 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-config/graphql-config.service.ts @@ -12,16 +12,16 @@ import GraphQLJSON from 'graphql-type-json'; import { GraphQLSchemaWithContext, YogaInitialContext } from 'graphql-yoga'; import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { useThrottler } from 'src/engine/api/graphql/graphql-config/hooks/use-throttler'; import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; import { CoreEngineModule } from 'src/engine/core-modules/core-engine.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { useSentryTracing } from 'src/engine/core-modules/exception-handler/hooks/use-sentry-tracing'; import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { handleExceptionAndConvertToGraphQLError } from 'src/engine/utils/global-exception-handler.util'; @@ -38,17 +38,17 @@ export class GraphQLConfigService { constructor( private readonly exceptionHandlerService: ExceptionHandlerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly moduleRef: ModuleRef, ) {} createGqlOptions(): YogaDriverConfig { const isDebugMode = - this.environmentService.get('NODE_ENV') === NodeEnvironment.development; + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development; const plugins = [ useThrottler({ - ttl: this.environmentService.get('API_RATE_LIMITING_TTL'), - limit: this.environmentService.get('API_RATE_LIMITING_LIMIT'), + ttl: this.twentyConfigService.get('API_RATE_LIMITING_TTL'), + limit: this.twentyConfigService.get('API_RATE_LIMITING_LIMIT'), identifyFn: (context) => { return context.req.user?.id ?? context.req.ip ?? 'anonymous'; }, diff --git a/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts b/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts index f7ac4328f21..d9962cdb030 100644 --- a/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/metadata-graphql-api.module.ts @@ -5,11 +5,11 @@ import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs'; import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module'; import { metadataModuleFactory } from 'src/engine/api/graphql/metadata.module-factory'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataloaderModule } from 'src/engine/dataloaders/dataloader.module'; import { DataloaderService } from 'src/engine/dataloaders/dataloader.service'; -import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module'; import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module'; @@ -21,7 +21,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor useFactory: metadataModuleFactory, imports: [GraphQLConfigModule, DataloaderModule], inject: [ - EnvironmentService, + TwentyConfigService, ExceptionHandlerService, DataloaderService, CacheStorageNamespace.EngineWorkspace, diff --git a/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts b/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts index eeed12f257c..c86eee4d9a5 100644 --- a/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/metadata.module-factory.ts @@ -1,20 +1,20 @@ import { YogaDriverConfig } from '@graphql-yoga/nestjs'; import GraphQLJSON from 'graphql-type-json'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { useCachedMetadata } from 'src/engine/api/graphql/graphql-config/hooks/use-cached-metadata'; import { useThrottler } from 'src/engine/api/graphql/graphql-config/hooks/use-throttler'; import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphql-api.module'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataloaderService } from 'src/engine/dataloaders/dataloader.service'; import { renderApolloPlayground } from 'src/engine/utils/render-apollo-playground.util'; export const metadataModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, exceptionHandlerService: ExceptionHandlerService, dataloaderService: DataloaderService, cacheStorageService: CacheStorageService, @@ -28,8 +28,8 @@ export const metadataModuleFactory = async ( resolvers: { JSON: GraphQLJSON }, plugins: [ useThrottler({ - ttl: environmentService.get('API_RATE_LIMITING_TTL'), - limit: environmentService.get('API_RATE_LIMITING_LIMIT'), + ttl: twentyConfigService.get('API_RATE_LIMITING_TTL'), + limit: twentyConfigService.get('API_RATE_LIMITING_LIMIT'), identifyFn: (context) => { return context.req.user?.id ?? context.req.ip ?? 'anonymous'; }, @@ -49,7 +49,7 @@ export const metadataModuleFactory = async ( }), }; - if (environmentService.get('NODE_ENV') === NodeEnvironment.development) { + if (twentyConfigService.get('NODE_ENV') === NodeEnvironment.development) { config.renderGraphiQL = () => { return renderApolloPlayground({ path: 'metadata' }); }; diff --git a/packages/twenty-server/src/engine/api/rest/rest-api.service.ts b/packages/twenty-server/src/engine/api/rest/rest-api.service.ts index 128df3f96b3..d69a01e6af9 100644 --- a/packages/twenty-server/src/engine/api/rest/rest-api.service.ts +++ b/packages/twenty-server/src/engine/api/rest/rest-api.service.ts @@ -1,13 +1,13 @@ -import { Injectable } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; +import { Injectable } from '@nestjs/common'; -import { Request } from 'express'; import { AxiosResponse } from 'axios'; +import { Request } from 'express'; import { Query } from 'src/engine/api/rest/core/types/query.type'; -import { getServerUrl } from 'src/utils/get-server-url'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { RestApiException } from 'src/engine/api/rest/errors/RestApiException'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { getServerUrl } from 'src/utils/get-server-url'; export enum GraphqlApiType { CORE = 'core', @@ -17,14 +17,14 @@ export enum GraphqlApiType { @Injectable() export class RestApiService { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly httpService: HttpService, ) {} async call(graphqlApiType: GraphqlApiType, request: Request, data: Query) { const baseUrl = getServerUrl( request, - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('SERVER_URL'), ); let response: AxiosResponse; const url = `${baseUrl}/${ diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts index c84a3af9551..521e99df194 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel-health.service.spec.ts @@ -8,7 +8,6 @@ import { HEALTH_INDICATORS } from 'src/engine/core-modules/admin-panel/constants import { SystemHealth } from 'src/engine/core-modules/admin-panel/dtos/system-health.dto'; import { AdminPanelHealthServiceStatus } from 'src/engine/core-modules/admin-panel/enums/admin-panel-health-service-status.enum'; import { QueueMetricsTimeRange } from 'src/engine/core-modules/admin-panel/enums/queue-metrics-time-range.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { HEALTH_ERROR_MESSAGES } from 'src/engine/core-modules/health/constants/health-error-messages.constants'; import { HealthIndicatorId } from 'src/engine/core-modules/health/enums/health-indicator-id.enum'; import { AppHealthIndicator } from 'src/engine/core-modules/health/indicators/app.health'; @@ -18,6 +17,7 @@ import { RedisHealthIndicator } from 'src/engine/core-modules/health/indicators/ import { WorkerHealthIndicator } from 'src/engine/core-modules/health/indicators/worker.health'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { RedisClientService } from 'src/engine/core-modules/redis-client/redis-client.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; jest.mock('bullmq'); @@ -29,7 +29,7 @@ describe('AdminPanelHealthService', () => { let connectedAccountHealth: jest.Mocked; let appHealth: jest.Mocked; let redisClient: jest.Mocked; - let environmentService: jest.Mocked; + let twentyConfigService: jest.Mocked; let loggerSpy: jest.SpyInstance; beforeEach(async () => { @@ -41,7 +41,7 @@ describe('AdminPanelHealthService', () => { redisClient = { getClient: jest.fn().mockReturnValue({} as Redis), } as any; - environmentService = { get: jest.fn() } as any; + twentyConfigService = { get: jest.fn() } as any; (Queue as unknown as jest.Mock) = jest.fn().mockImplementation(() => ({ getMetrics: jest.fn(), @@ -58,7 +58,7 @@ describe('AdminPanelHealthService', () => { { provide: ConnectedAccountHealth, useValue: connectedAccountHealth }, { provide: AppHealthIndicator, useValue: appHealth }, { provide: RedisClientService, useValue: redisClient }, - { provide: EnvironmentService, useValue: environmentService }, + { provide: TwentyConfigService, useValue: twentyConfigService }, ], }).compile(); diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts index a47d09ad7e5..1c0605adacc 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/__tests__/admin-panel.service.spec.ts @@ -10,17 +10,17 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; const UserFindOneMock = jest.fn(); const LoginTokenServiceGenerateLoginTokenMock = jest.fn(); -const EnvironmentServiceGetAllMock = jest.fn(); +const TwentyConfigServiceGetAllMock = jest.fn(); jest.mock( - '../../environment/constants/environment-variables-group-metadata', + 'src/engine/core-modules/twenty-config/constants/config-variables-group-metadata', () => ({ - ENVIRONMENT_VARIABLES_GROUP_METADATA: { + CONFIG_VARIABLES_GROUP_METADATA: { SERVER_CONFIG: { position: 100, description: 'Server config description', @@ -69,9 +69,9 @@ describe('AdminPanelService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { - getAll: EnvironmentServiceGetAllMock, + getAll: TwentyConfigServiceGetAllMock, }, }, ], @@ -157,9 +157,9 @@ describe('AdminPanelService', () => { expect(UserFindOneMock).toHaveBeenCalled(); }); - describe('getEnvironmentVariablesGrouped', () => { - it('should correctly group and sort environment variables', () => { - EnvironmentServiceGetAllMock.mockReturnValue({ + describe('getConfigVariablesGrouped', () => { + it('should correctly group and sort config variables', () => { + TwentyConfigServiceGetAllMock.mockReturnValue({ SERVER_URL: { value: 'http://localhost', metadata: { @@ -179,7 +179,7 @@ describe('AdminPanelService', () => { metadata: { group: 'SERVER_CONFIG', description: 'API Key', - sensitive: true, + isSensitive: true, }, }, OTHER_VAR: { @@ -191,7 +191,7 @@ describe('AdminPanelService', () => { }, }); - const result = service.getEnvironmentVariablesGrouped(); + const result = service.getConfigVariablesGrouped(); expect(result).toEqual({ groups: [ @@ -204,13 +204,13 @@ describe('AdminPanelService', () => { name: 'API_KEY', value: 'secret-key', description: 'API Key', - sensitive: true, + isSensitive: true, }, { name: 'SERVER_URL', value: 'http://localhost', description: 'Server URL', - sensitive: false, + isSensitive: false, }, ], }, @@ -223,7 +223,7 @@ describe('AdminPanelService', () => { name: 'RATE_LIMIT_TTL', value: '60', description: 'Rate limit TTL', - sensitive: false, + isSensitive: false, }, ], }, @@ -236,7 +236,7 @@ describe('AdminPanelService', () => { name: 'OTHER_VAR', value: 'other', description: 'Other var', - sensitive: false, + isSensitive: false, }, ], }, @@ -248,10 +248,10 @@ describe('AdminPanelService', () => { expect(result.groups[2].name).toBe('OTHER'); }); - it('should handle empty environment variables', () => { - EnvironmentServiceGetAllMock.mockReturnValue({}); + it('should handle empty config variables', () => { + TwentyConfigServiceGetAllMock.mockReturnValue({}); - const result = service.getEnvironmentVariablesGrouped(); + const result = service.getConfigVariablesGrouped(); expect(result).toEqual({ groups: [], @@ -259,7 +259,7 @@ describe('AdminPanelService', () => { }); it('should handle variables with undefined metadata fields', () => { - EnvironmentServiceGetAllMock.mockReturnValue({ + TwentyConfigServiceGetAllMock.mockReturnValue({ TEST_VAR: { value: 'test', metadata: { @@ -268,13 +268,13 @@ describe('AdminPanelService', () => { }, }); - const result = service.getEnvironmentVariablesGrouped(); + const result = service.getConfigVariablesGrouped(); expect(result.groups[0].variables[0]).toEqual({ name: 'TEST_VAR', value: 'test', description: undefined, - sensitive: false, + isSensitive: false, }); }); }); @@ -287,7 +287,7 @@ describe('AdminPanelService', () => { mockEnvironmentGet.mockReset(); mockAxiosGet.mockReset(); jest.spyOn(axios, 'get').mockImplementation(mockAxiosGet); - service['environmentService'].get = mockEnvironmentGet; + service['twentyConfigService'].get = mockEnvironmentGet; }); it('should return current and latest version when everything works', async () => { diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts index 42a5bfb5bd8..976d761cb40 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.resolver.ts @@ -3,7 +3,7 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { AdminPanelHealthService } from 'src/engine/core-modules/admin-panel/admin-panel-health.service'; import { AdminPanelService } from 'src/engine/core-modules/admin-panel/admin-panel.service'; -import { EnvironmentVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/environment-variables.output'; +import { ConfigVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/config-variables.output'; import { ImpersonateInput } from 'src/engine/core-modules/admin-panel/dtos/impersonate.input'; import { ImpersonateOutput } from 'src/engine/core-modules/admin-panel/dtos/impersonate.output'; import { SystemHealth } from 'src/engine/core-modules/admin-panel/dtos/system-health.dto'; @@ -17,7 +17,6 @@ import { FeatureFlagException } from 'src/engine/core-modules/feature-flag/featu import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { HealthIndicatorId } from 'src/engine/core-modules/health/enums/health-indicator-id.enum'; -import { WorkerHealthIndicator } from 'src/engine/core-modules/health/indicators/worker.health'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { AdminPanelGuard } from 'src/engine/guards/admin-panel-guard'; import { ImpersonateGuard } from 'src/engine/guards/impersonate-guard'; @@ -33,7 +32,6 @@ export class AdminPanelResolver { constructor( private adminService: AdminPanelService, private adminPanelHealthService: AdminPanelHealthService, - private workerHealthIndicator: WorkerHealthIndicator, private featureFlagService: FeatureFlagService, ) {} @@ -76,9 +74,9 @@ export class AdminPanelResolver { } @UseGuards(WorkspaceAuthGuard, UserAuthGuard, AdminPanelGuard) - @Query(() => EnvironmentVariablesOutput) - async getEnvironmentVariablesGrouped(): Promise { - return this.adminService.getEnvironmentVariablesGrouped(); + @Query(() => ConfigVariablesOutput) + async getConfigVariablesGrouped(): Promise { + return this.adminService.getConfigVariablesGrouped(); } @UseGuards(WorkspaceAuthGuard, UserAuthGuard, AdminPanelGuard) diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts index 110ea9a3b77..a729d0b6623 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/admin-panel.service.ts @@ -5,9 +5,9 @@ import axios from 'axios'; import semver from 'semver'; import { Repository } from 'typeorm'; -import { EnvironmentVariable } from 'src/engine/core-modules/admin-panel/dtos/environment-variable.dto'; -import { EnvironmentVariablesGroupData } from 'src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto'; -import { EnvironmentVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/environment-variables.output'; +import { ConfigVariable } from 'src/engine/core-modules/admin-panel/dtos/config-variable.dto'; +import { ConfigVariablesGroupData } from 'src/engine/core-modules/admin-panel/dtos/config-variables-group.dto'; +import { ConfigVariablesOutput } from 'src/engine/core-modules/admin-panel/dtos/config-variables.output'; import { UserLookup } from 'src/engine/core-modules/admin-panel/dtos/user-lookup.entity'; import { VersionInfo } from 'src/engine/core-modules/admin-panel/dtos/version-info.dto'; import { @@ -16,11 +16,11 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { ENVIRONMENT_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/environment/constants/environment-variables-group-metadata'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { CONFIG_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/twenty-config/constants/config-variables-group-metadata'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { userValidator } from 'src/engine/core-modules/user/user.validate'; @@ -28,7 +28,7 @@ import { userValidator } from 'src/engine/core-modules/user/user.validate'; export class AdminPanelService { constructor( private readonly loginTokenService: LoginTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, @InjectRepository(User, 'core') private readonly userRepository: Repository, @@ -123,21 +123,18 @@ export class AdminPanelService { }; } - getEnvironmentVariablesGrouped(): EnvironmentVariablesOutput { - const rawEnvVars = this.environmentService.getAll(); - const groupedData = new Map< - EnvironmentVariablesGroup, - EnvironmentVariable[] - >(); + getConfigVariablesGrouped(): ConfigVariablesOutput { + const rawEnvVars = this.twentyConfigService.getAll(); + const groupedData = new Map(); for (const [varName, { value, metadata }] of Object.entries(rawEnvVars)) { const { group, description } = metadata; - const envVar: EnvironmentVariable = { + const envVar: ConfigVariable = { name: varName, description, value: String(value), - sensitive: metadata.sensitive ?? false, + isSensitive: metadata.isSensitive ?? false, }; if (!groupedData.has(group)) { @@ -147,20 +144,17 @@ export class AdminPanelService { groupedData.get(group)?.push(envVar); } - const groups: EnvironmentVariablesGroupData[] = Array.from( - groupedData.entries(), - ) + const groups: ConfigVariablesGroupData[] = Array.from(groupedData.entries()) .sort((a, b) => { - const positionA = ENVIRONMENT_VARIABLES_GROUP_METADATA[a[0]].position; - const positionB = ENVIRONMENT_VARIABLES_GROUP_METADATA[b[0]].position; + const positionA = CONFIG_VARIABLES_GROUP_METADATA[a[0]].position; + const positionB = CONFIG_VARIABLES_GROUP_METADATA[b[0]].position; return positionA - positionB; }) .map(([name, variables]) => ({ name, - description: ENVIRONMENT_VARIABLES_GROUP_METADATA[name].description, - isHiddenOnLoad: - ENVIRONMENT_VARIABLES_GROUP_METADATA[name].isHiddenOnLoad, + description: CONFIG_VARIABLES_GROUP_METADATA[name].description, + isHiddenOnLoad: CONFIG_VARIABLES_GROUP_METADATA[name].isHiddenOnLoad, variables: variables.sort((a, b) => a.name.localeCompare(b.name)), })); @@ -168,7 +162,7 @@ export class AdminPanelService { } async getVersionInfo(): Promise { - const currentVersion = this.environmentService.get('APP_VERSION'); + const currentVersion = this.twentyConfigService.get('APP_VERSION'); try { const response = await axios.get( diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variable.dto.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variable.dto.ts similarity index 75% rename from packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variable.dto.ts rename to packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variable.dto.ts index fa1a7c1e083..290731f3e7f 100644 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variable.dto.ts +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variable.dto.ts @@ -1,7 +1,7 @@ import { Field, ObjectType } from '@nestjs/graphql'; @ObjectType() -export class EnvironmentVariable { +export class ConfigVariable { @Field() name: string; @@ -12,5 +12,5 @@ export class EnvironmentVariable { value: string; @Field() - sensitive: boolean; + isSensitive: boolean; } diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts new file mode 100644 index 00000000000..b2a7f9f84e9 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables-group.dto.ts @@ -0,0 +1,23 @@ +import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; + +import { ConfigVariable } from 'src/engine/core-modules/admin-panel/dtos/config-variable.dto'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; + +registerEnumType(ConfigVariablesGroup, { + name: 'ConfigVariablesGroup', +}); + +@ObjectType() +export class ConfigVariablesGroupData { + @Field(() => [ConfigVariable]) + variables: ConfigVariable[]; + + @Field(() => ConfigVariablesGroup) + name: ConfigVariablesGroup; + + @Field(() => String, { defaultValue: '' }) + description: string; + + @Field(() => Boolean, { defaultValue: false }) + isHiddenOnLoad: boolean; +} diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts new file mode 100644 index 00000000000..8df5acc6068 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/config-variables.output.ts @@ -0,0 +1,9 @@ +import { Field, ObjectType } from '@nestjs/graphql'; + +import { ConfigVariablesGroupData } from 'src/engine/core-modules/admin-panel/dtos/config-variables-group.dto'; + +@ObjectType() +export class ConfigVariablesOutput { + @Field(() => [ConfigVariablesGroupData]) + groups: ConfigVariablesGroupData[]; +} diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts deleted file mode 100644 index bc75ceb2cfa..00000000000 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables-group.dto.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; - -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; - -import { EnvironmentVariable } from './environment-variable.dto'; - -registerEnumType(EnvironmentVariablesGroup, { - name: 'EnvironmentVariablesGroup', -}); - -@ObjectType() -export class EnvironmentVariablesGroupData { - @Field(() => [EnvironmentVariable]) - variables: EnvironmentVariable[]; - - @Field(() => EnvironmentVariablesGroup) - name: EnvironmentVariablesGroup; - - @Field(() => String, { defaultValue: '' }) - description: string; - - @Field(() => Boolean, { defaultValue: false }) - isHiddenOnLoad: boolean; -} diff --git a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts b/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts deleted file mode 100644 index 02e98d388bf..00000000000 --- a/packages/twenty-server/src/engine/core-modules/admin-panel/dtos/environment-variables.output.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; - -import { EnvironmentVariablesGroupData } from './environment-variables-group.dto'; - -@ObjectType() -export class EnvironmentVariablesOutput { - @Field(() => [EnvironmentVariablesGroupData]) - groups: EnvironmentVariablesGroupData[]; -} diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts index 36feaed4d46..c4818ff2c35 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.spec.ts @@ -1,8 +1,8 @@ import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { AnalyticsService } from './analytics.service'; @@ -14,7 +14,7 @@ describe('AnalyticsService', () => { providers: [ AnalyticsService, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, { diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts index b0cc7788bb9..01e3fcebc73 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; type CreateEventInput = { action: string; @@ -9,14 +9,14 @@ type CreateEventInput = { @Injectable() export class AnalyticsService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} async create( createEventInput: CreateEventInput, userId: string | null | undefined, workspaceId: string | null | undefined, ) { - if (!this.environmentService.get('ANALYTICS_ENABLED')) { + if (!this.twentyConfigService.get('ANALYTICS_ENABLED')) { return { success: true }; } diff --git a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts index b6bdefde341..b9b57f43f12 100644 --- a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts +++ b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.service.ts @@ -16,7 +16,7 @@ import { import { approvedAccessDomainValidator } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.validate'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { isWorkDomain } from 'src/utils/is-work-email'; @@ -28,7 +28,7 @@ export class ApprovedAccessDomainService { @InjectRepository(ApprovedAccessDomainEntity, 'core') private readonly approvedAccessDomainRepository: Repository, private readonly emailService: EmailService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, ) {} @@ -70,7 +70,7 @@ export class ApprovedAccessDomainService { firstName: sender.firstName, lastName: sender.lastName, }, - serverUrl: this.environmentService.get('SERVER_URL'), + serverUrl: this.twentyConfigService.get('SERVER_URL'), locale: 'en' as keyof typeof APP_LOCALES, }); const html = await render(emailTemplate); @@ -79,7 +79,7 @@ export class ApprovedAccessDomainService { }); await this.emailService.send({ - from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to, subject: 'Approve your access domain', text, @@ -94,7 +94,7 @@ export class ApprovedAccessDomainService { JSON.stringify({ id: approvedAccessDomain.id, domain: approvedAccessDomain.domain, - key: this.environmentService.get('APP_SECRET'), + key: this.twentyConfigService.get('APP_SECRET'), }), ) .digest('hex'); diff --git a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts index 6914161c43f..e18db65b568 100644 --- a/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/approved-access-domain/services/approved-access-domain.spec.ts @@ -3,16 +3,16 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { DeleteResult, Repository } from 'typeorm'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { ApprovedAccessDomain } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.entity'; import { ApprovedAccessDomainException, ApprovedAccessDomainExceptionCode, } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.exception'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { EmailService } from 'src/engine/core-modules/email/email.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { ApprovedAccessDomainService } from './approved-access-domain.service'; @@ -20,7 +20,7 @@ describe('ApprovedAccessDomainService', () => { let service: ApprovedAccessDomainService; let approvedAccessDomainRepository: Repository; let emailService: EmailService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -43,7 +43,7 @@ describe('ApprovedAccessDomainService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -64,7 +64,7 @@ describe('ApprovedAccessDomainService', () => { getRepositoryToken(ApprovedAccessDomain, 'core'), ); emailService = module.get(EmailService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); }); @@ -267,7 +267,7 @@ describe('ApprovedAccessDomainService', () => { .mockReturnValue(new URL('https://sub.twenty.com')); jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { if (key === 'EMAIL_FROM_ADDRESS') return 'no-reply@example.com'; if (key === 'SERVER_URL') return 'https://api.example.com'; diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts index cbac8c65d77..15574a13fed 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/google-apis-auth.controller.ts @@ -22,9 +22,9 @@ import { GoogleAPIsService } from 'src/engine/core-modules/auth/services/google- import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Controller('auth/google-apis') @@ -33,7 +33,7 @@ export class GoogleAPIsAuthController { constructor( private readonly googleAPIsService: GoogleAPIsService, private readonly transientTokenService: TransientTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly onboardingService: OnboardingService, private readonly domainManagerService: DomainManagerService, private readonly guardRedirectService: GuardRedirectService, @@ -123,7 +123,7 @@ export class GoogleAPIsAuthController { this.guardRedirectService.getRedirectErrorUrlAndCaptureExceptions( err, workspace ?? { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }, ), diff --git a/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts b/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts index d7ca0509a66..c0e062804b3 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/controllers/microsoft-apis-auth.controller.ts @@ -22,9 +22,9 @@ import { MicrosoftAPIsService } from 'src/engine/core-modules/auth/services/micr import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { MicrosoftAPIsRequest } from 'src/engine/core-modules/auth/types/microsoft-api-request.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Controller('auth/microsoft-apis') @@ -33,7 +33,7 @@ export class MicrosoftAPIsAuthController { constructor( private readonly microsoftAPIsService: MicrosoftAPIsService, private readonly transientTokenService: TransientTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly onboardingService: OnboardingService, private readonly guardRedirectService: GuardRedirectService, @@ -130,7 +130,7 @@ export class MicrosoftAPIsAuthController { this.guardRedirectService.getRedirectErrorUrlAndCaptureExceptions( err, workspace ?? { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }, ), diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts index 2f7e925871d..4c547a2696c 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/enterprise-features-enabled.guard.ts @@ -6,19 +6,19 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class EnterpriseFeaturesEnabledGuard implements CanActivate { constructor( private readonly guardRedirectService: GuardRedirectService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} canActivate(context: ExecutionContext): boolean { try { - if (!this.environmentService.get('ENTERPRISE_KEY')) { + if (!this.twentyConfigService.get('ENTERPRISE_KEY')) { throw new AuthException( 'Enterprise key missing', AuthExceptionCode.MISSING_ENVIRONMENT_VARIABLE, diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts index 3e6c57fac86..0d32c2fa4bb 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-exchange-code-for-token.guard.ts @@ -7,8 +7,8 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { GoogleAPIsOauthExchangeCodeForTokenStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( @@ -16,7 +16,7 @@ export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( ) { constructor( private readonly guardRedirectService: GuardRedirectService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { super(); } @@ -27,8 +27,8 @@ export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( const state = JSON.parse(request.query.state); if ( - !this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') ) { throw new AuthException( 'Google apis auth is not enabled', @@ -36,7 +36,7 @@ export class GoogleAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( ); } - new GoogleAPIsOauthExchangeCodeForTokenStrategy(this.environmentService); + new GoogleAPIsOauthExchangeCodeForTokenStrategy(this.twentyConfigService); setRequestExtraParams(request, { transientToken: state.transientToken, diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts index 834fdd7d8ea..038aba1abd6 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-apis-oauth-request-code.guard.ts @@ -11,15 +11,15 @@ import { import { GoogleAPIsOauthRequestCodeStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy'; import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly transientTokenService: TransientTokenService, private readonly guardRedirectService: GuardRedirectService, @InjectRepository(Workspace, 'core') @@ -57,8 +57,8 @@ export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { }); if ( - !this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_GOOGLE_ENABLED') ) { throw new AuthException( 'Google apis auth is not enabled', @@ -66,7 +66,7 @@ export class GoogleAPIsOauthRequestCodeGuard extends AuthGuard('google-apis') { ); } - new GoogleAPIsOauthRequestCodeStrategy(this.environmentService); + new GoogleAPIsOauthRequestCodeStrategy(this.twentyConfigService); return (await super.canActivate(context)) as boolean; } catch (err) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts index 731caf7694a..1d57f750e4b 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/google-provider-enabled.guard.ts @@ -5,26 +5,26 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { GoogleStrategy } from 'src/engine/core-modules/auth/strategies/google.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class GoogleProviderEnabledGuard implements CanActivate { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly guardRedirectService: GuardRedirectService, ) {} canActivate(context: ExecutionContext): boolean { try { - if (!this.environmentService.get('AUTH_GOOGLE_ENABLED')) { + if (!this.twentyConfigService.get('AUTH_GOOGLE_ENABLED')) { throw new AuthException( 'Google auth is not enabled', AuthExceptionCode.GOOGLE_API_AUTH_DISABLED, ); } - new GoogleStrategy(this.environmentService); + new GoogleStrategy(this.twentyConfigService); return true; } catch (err) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts index c814fe821bf..d26c5fdf2e5 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-exchange-code-for-token.guard.ts @@ -7,8 +7,8 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { MicrosoftAPIsOauthExchangeCodeForTokenStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( @@ -16,7 +16,7 @@ export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( ) { constructor( private readonly guardRedirectService: GuardRedirectService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { super(); } @@ -27,8 +27,8 @@ export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( const state = JSON.parse(request.query.state); if ( - !this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') ) { throw new AuthException( 'Microsoft apis auth is not enabled', @@ -37,7 +37,7 @@ export class MicrosoftAPIsOauthExchangeCodeForTokenGuard extends AuthGuard( } new MicrosoftAPIsOauthExchangeCodeForTokenStrategy( - this.environmentService, + this.twentyConfigService, ); setRequestExtraParams(request, { diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts index 877a1d00748..82504a2a9f9 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-apis-oauth-request-code.guard.ts @@ -11,17 +11,17 @@ import { import { MicrosoftAPIsOauthRequestCodeStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy'; import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { setRequestExtraParams } from 'src/engine/core-modules/auth/utils/google-apis-set-request-extra-params.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() export class MicrosoftAPIsOauthRequestCodeGuard extends AuthGuard( 'microsoft-apis', ) { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly transientTokenService: TransientTokenService, private readonly guardRedirectService: GuardRedirectService, @InjectRepository(Workspace, 'core') @@ -38,8 +38,8 @@ export class MicrosoftAPIsOauthRequestCodeGuard extends AuthGuard( try { if ( - !this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && - !this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') + !this.twentyConfigService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED') && + !this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') ) { throw new AuthException( 'Microsoft apis auth is not enabled', @@ -58,7 +58,7 @@ export class MicrosoftAPIsOauthRequestCodeGuard extends AuthGuard( id: workspaceId, }); - new MicrosoftAPIsOauthRequestCodeStrategy(this.environmentService); + new MicrosoftAPIsOauthRequestCodeStrategy(this.twentyConfigService); setRequestExtraParams(request, { transientToken: request.query.transientToken, redirectLocation: request.query.redirectLocation, diff --git a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts index 9b29bae0ba3..fdba7cc3179 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/guards/microsoft-provider-enabled.guard.ts @@ -5,26 +5,26 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { MicrosoftStrategy } from 'src/engine/core-modules/auth/strategies/microsoft.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftProviderEnabledGuard implements CanActivate { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly guardRedirectService: GuardRedirectService, ) {} canActivate(context: ExecutionContext): boolean { try { - if (!this.environmentService.get('AUTH_MICROSOFT_ENABLED')) { + if (!this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED')) { throw new AuthException( 'Microsoft auth is not enabled', AuthExceptionCode.MICROSOFT_API_AUTH_DISABLED, ); } - new MicrosoftStrategy(this.environmentService); + new MicrosoftStrategy(this.twentyConfigService); return true; } catch (err) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts index 7159269ec85..bff67b54edb 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.spec.ts @@ -1,14 +1,14 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ApiKeyService } from './api-key.service'; describe('ApiKeyService', () => { let service: ApiKeyService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -22,7 +22,7 @@ describe('ApiKeyService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -32,7 +32,7 @@ describe('ApiKeyService', () => { service = module.get(ApiKeyService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); it('should be defined', () => { @@ -51,7 +51,7 @@ describe('ApiKeyService', () => { const apiKeyId = 'api-key-id'; const mockToken = 'mock-token'; - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); jest.spyOn(jwtWrapperService, 'sign').mockReturnValue(mockToken); jest .spyOn(jwtWrapperService, 'generateAppSecret') diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts index f6bad822216..85c51dcac54 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/api-key.service.ts @@ -1,14 +1,14 @@ import { Injectable } from '@nestjs/common'; import { ApiKeyToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class ApiKeyService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateApiKeyToken( diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts index 30ef9996a59..a779b8c58b3 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.service.ts @@ -3,16 +3,16 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() export class AuthSsoService { constructor( @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} private getAuthProviderColumnNameByProvider( @@ -41,7 +41,7 @@ export class AuthSsoService { workspaceId?: string, ) { if ( - this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') && + this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED') && !workspaceId ) { // Multi-workspace enable mode but on non workspace url. diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts index 7f2ff2ecaf8..1fbba06ad66 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth-sso.spec.ts @@ -4,13 +4,13 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { AuthSsoService } from 'src/engine/core-modules/auth/services/auth-sso.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; describe('AuthSsoService', () => { let authSsoService: AuthSsoService; let workspaceRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -23,7 +23,7 @@ describe('AuthSsoService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -35,7 +35,7 @@ describe('AuthSsoService', () => { workspaceRepository = module.get>( getRepositoryToken(Workspace, 'core'), ); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); describe('findWorkspaceFromWorkspaceIdOrAuthProvider', () => { @@ -67,7 +67,7 @@ describe('AuthSsoService', () => { const email = 'test@example.com'; const mockWorkspace = { id: 'workspace-id-456' } as Workspace; - jest.spyOn(environmentService, 'get').mockReturnValue(true); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(true); jest .spyOn(workspaceRepository, 'findOne') .mockResolvedValue(mockWorkspace); @@ -97,7 +97,7 @@ describe('AuthSsoService', () => { }); it('should return undefined if no workspace is found when multi-workspace mode is enabled', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue(true); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(true); jest.spyOn(workspaceRepository, 'findOne').mockResolvedValue(null); const result = @@ -110,7 +110,7 @@ describe('AuthSsoService', () => { }); it('should throw an error for an invalid authProvider', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue(true); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(true); await expect( authSsoService.findWorkspaceFromWorkspaceIdOrAuthProvider({ diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts index c18b794aeae..3dc84386d64 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.spec.ts @@ -16,7 +16,7 @@ import { RefreshTokenService } from 'src/engine/core-modules/auth/token/services import { ExistingUserOrNewUser } from 'src/engine/core-modules/auth/types/signInUp.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -35,7 +35,7 @@ const workspaceInvitationGetOneWorkspaceInvitationMock = jest.fn(); const workspaceInvitationValidatePersonalInvitationMock = jest.fn(); const userWorkspaceAddUserToWorkspaceMock = jest.fn(); -const environmentServiceGetMock = jest.fn(); +const twentyConfigServiceGetMock = jest.fn(); describe('AuthService', () => { let service: AuthService; @@ -75,9 +75,9 @@ describe('AuthService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { - get: environmentServiceGetMock, + get: twentyConfigServiceGetMock, }, }, { @@ -138,7 +138,7 @@ describe('AuthService', () => { }); beforeEach(() => { - environmentServiceGetMock.mockReturnValue(false); + twentyConfigServiceGetMock.mockReturnValue(false); }); it('should be defined', async () => { diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts index 64d03914a03..9b7117301f3 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/auth.service.ts @@ -13,7 +13,7 @@ import { APP_LOCALES } from 'twenty-shared/translations'; import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { AppToken, @@ -51,7 +51,7 @@ import { import { WorkspaceSubdomainCustomDomainAndIsCustomDomainEnabledType } from 'src/engine/core-modules/domain-manager/domain-manager.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -77,7 +77,7 @@ export class AuthService { private readonly workspaceRepository: Repository, @InjectRepository(User, 'core') private readonly userRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly emailService: EmailService, @InjectRepository(AppToken, 'core') private readonly appTokenRepository: Repository, @@ -164,7 +164,7 @@ export class AuthService { ); } - const isEmailVerificationRequired = this.environmentService.get( + const isEmailVerificationRequired = this.twentyConfigService.get( 'IS_EMAIL_VERIFICATION_REQUIRED', ); @@ -323,10 +323,10 @@ export class AuthService { id: 'chrome', name: 'Chrome Extension', redirectUrl: - this.environmentService.get('NODE_ENV') === + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? authorizeAppInput.redirectUrl - : `https://${this.environmentService.get( + : `https://${this.twentyConfigService.get( 'CHROME_EXTENSION_ID', )}.chromiumapp.org/`, }, @@ -448,9 +448,9 @@ export class AuthService { i18n.activate(locale); this.emailService.send({ - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: user.email, subject: t`Your Password Has Been Successfully Changed`, text, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index 3621f4737bd..8baa9a08cc8 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -1,16 +1,16 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { ConnectedAccountProvider } from 'twenty-shared/types'; import { EntityManager, Repository } from 'typeorm'; import { v4 } from 'uuid'; -import { ConnectedAccountProvider } from 'twenty-shared/types'; import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { getGoogleApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; @@ -45,7 +45,7 @@ export class GoogleAPIsService { private readonly messageQueueService: MessageQueueService, @InjectMessageQueue(MessageQueue.calendarQueue) private readonly calendarQueueService: MessageQueueService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly accountsToReconnectService: AccountsToReconnectService, private readonly workspaceEventEmitter: WorkspaceEventEmitter, @InjectRepository(ObjectMetadataEntity, 'metadata') @@ -69,7 +69,7 @@ export class GoogleAPIsService { messageVisibility, } = input; - const isCalendarEnabled = this.environmentService.get( + const isCalendarEnabled = this.twentyConfigService.get( 'CALENDAR_PROVIDER_GOOGLE_ENABLED', ); @@ -300,7 +300,7 @@ export class GoogleAPIsService { } }); - if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) { + if (this.twentyConfigService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) { const messageChannels = await messageChannelRepository.find({ where: { connectedAccountId: newOrExistingConnectedAccountId, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts index 0ca3ed6fd53..de544b30285 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts @@ -1,16 +1,16 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { ConnectedAccountProvider } from 'twenty-shared/types'; import { EntityManager, Repository } from 'typeorm'; import { v4 } from 'uuid'; -import { ConnectedAccountProvider } from 'twenty-shared/types'; import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { getMicrosoftApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; @@ -51,7 +51,7 @@ export class MicrosoftAPIsService { private readonly workspaceEventEmitter: WorkspaceEventEmitter, @InjectRepository(ObjectMetadataEntity, 'metadata') private readonly objectMetadataRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async refreshMicrosoftRefreshToken(input: { @@ -200,7 +200,7 @@ export class MicrosoftAPIsService { }); if ( - this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') + this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED') ) { const newCalendarChannel = await calendarChannelRepository.save( { @@ -328,7 +328,7 @@ export class MicrosoftAPIsService { } }); - if (this.environmentService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED')) { + if (this.twentyConfigService.get('MESSAGING_PROVIDER_MICROSOFT_ENABLED')) { const messageChannels = await messageChannelRepository.find({ where: { connectedAccountId: newOrExistingConnectedAccountId, @@ -346,7 +346,7 @@ export class MicrosoftAPIsService { } } - if (this.environmentService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')) { + if (this.twentyConfigService.get('CALENDAR_PROVIDER_MICROSOFT_ENABLED')) { const calendarChannels = await calendarChannelRepository.find({ where: { connectedAccountId: newOrExistingConnectedAccountId, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts index 2939b9b3b2f..c573a6e81d2 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.spec.ts @@ -11,7 +11,7 @@ import { import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -23,7 +23,7 @@ describe('ResetPasswordService', () => { let workspaceRepository: Repository; let appTokenRepository: Repository; let emailService: EmailService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -62,7 +62,7 @@ describe('ResetPasswordService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -81,7 +81,7 @@ describe('ResetPasswordService', () => { getRepositoryToken(AppToken, 'core'), ); emailService = module.get(EmailService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); }); @@ -99,7 +99,7 @@ describe('ResetPasswordService', () => { .mockResolvedValue(mockUser as User); jest.spyOn(appTokenRepository, 'findOne').mockResolvedValue(null); jest.spyOn(appTokenRepository, 'save').mockResolvedValue({} as AppToken); - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); const result = await service.generatePasswordResetToken( 'test@example.com', @@ -165,7 +165,7 @@ describe('ResetPasswordService', () => { .spyOn(workspaceRepository, 'findOneBy') .mockResolvedValue({ id: 'workspace-id' } as Workspace); jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockReturnValue('http://localhost:3000'); jest .spyOn(domainManagerService, 'buildWorkspaceURL') diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts index 7a7f567c673..997c0f7c56d 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/reset-password.service.ts @@ -26,7 +26,7 @@ import { PasswordResetToken } from 'src/engine/core-modules/auth/dto/token.entit import { ValidatePasswordResetToken } from 'src/engine/core-modules/auth/dto/validate-password-reset-token.entity'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate'; @@ -34,7 +34,7 @@ import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace. @Injectable() export class ResetPasswordService { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, @InjectRepository(User, 'core') private readonly userRepository: Repository, @@ -60,7 +60,7 @@ export class ResetPasswordService { ); } - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'PASSWORD_RESET_TOKEN_EXPIRES_IN', ); @@ -164,9 +164,9 @@ export class ResetPasswordService { i18n.activate(locale); this.emailService.send({ - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: email, subject: t`Action Needed to Reset Password`, text, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts index d6caff56050..3a079cb7182 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts @@ -2,8 +2,8 @@ import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { @@ -17,10 +17,10 @@ import { SignInUpBaseParams, } from 'src/engine/core-modules/auth/types/signInUp.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @@ -42,7 +42,7 @@ describe('SignInUpService', () => { let fileUploadService: FileUploadService; let workspaceInvitationService: WorkspaceInvitationService; let userWorkspaceService: UserWorkspaceService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -98,7 +98,7 @@ describe('SignInUpService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -143,7 +143,7 @@ describe('SignInUpService', () => { ); userWorkspaceService = module.get(UserWorkspaceService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); }); @@ -242,7 +242,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest.spyOn(WorkspaceRepository, 'count').mockResolvedValue(0); jest.spyOn(WorkspaceRepository, 'create').mockReturnValue({} as Workspace); jest.spyOn(WorkspaceRepository, 'save').mockResolvedValue({ @@ -292,7 +292,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest .spyOn(userWorkspaceService, 'addUserToWorkspaceIfUserNotInWorkspace') .mockResolvedValue(undefined); @@ -324,7 +324,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest .spyOn(userWorkspaceService, 'checkUserWorkspaceExists') .mockResolvedValue(null); @@ -349,7 +349,7 @@ describe('SignInUpService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue(false); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(false); jest.spyOn(WorkspaceRepository, 'count').mockResolvedValue(0); jest.spyOn(WorkspaceRepository, 'create').mockReturnValue({} as Workspace); jest.spyOn(WorkspaceRepository, 'save').mockResolvedValue({ diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts index 5a59d01a88f..beb6715b39e 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts @@ -3,10 +3,10 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import FileType from 'file-type'; -import { Repository } from 'typeorm'; -import { v4 } from 'uuid'; import { TWENTY_ICONS_BASE_URL } from 'twenty-shared/constants'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; +import { v4 } from 'uuid'; import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; @@ -28,10 +28,10 @@ import { SignInUpNewUserPayload, } from 'src/engine/core-modules/auth/types/signInUp.type'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -55,7 +55,7 @@ export class SignInUpService { private readonly userWorkspaceService: UserWorkspaceService, private readonly onboardingService: OnboardingService, private readonly httpService: HttpService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly userService: UserService, private readonly userRoleService: UserRoleService, @@ -324,7 +324,7 @@ export class SignInUpService { ); } - if (!this.environmentService.get('IS_MULTIWORKSPACE_ENABLED')) { + if (!this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED')) { const workspacesCount = await this.workspaceRepository.count(); // if the workspace doesn't exist it means it's the first user of the workspace diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts index 36351e2a49f..de7c1943f5c 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy.ts @@ -3,8 +3,8 @@ import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-google-oauth20'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { getGoogleApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -16,13 +16,13 @@ export class GoogleAPIsOauthCommonStrategy extends PassportStrategy( Strategy, 'google-apis', ) { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { const scopes = getGoogleApisOauthScopes(); super({ - clientID: environmentService.get('AUTH_GOOGLE_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_GOOGLE_CLIENT_SECRET'), - callbackURL: environmentService.get('AUTH_GOOGLE_APIS_CALLBACK_URL'), + clientID: twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_GOOGLE_CLIENT_SECRET'), + callbackURL: twentyConfigService.get('AUTH_GOOGLE_APIS_CALLBACK_URL'), scope: scopes, passReqToCallback: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts index 1b89939b621..f10e63f5ad5 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-exchange-code-for-token.auth.strategy.ts @@ -4,7 +4,7 @@ import { VerifyCallback } from 'passport-google-oauth20'; import { GoogleAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy'; import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -12,8 +12,8 @@ export type GoogleAPIScopeConfig = { @Injectable() export class GoogleAPIsOauthExchangeCodeForTokenStrategy extends GoogleAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } async validate( diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts index 0eda93a5b49..b5339f5afb3 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google-apis-oauth-request-code.auth.strategy.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { GoogleAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/google-apis-oauth-common.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -10,8 +10,8 @@ export type GoogleAPIScopeConfig = { @Injectable() export class GoogleAPIsOauthRequestCodeStrategy extends GoogleAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } authenticate(req: any, options: any) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts index 5a6fe9e0940..d2f132eaf2a 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/google.auth.strategy.ts @@ -5,7 +5,7 @@ import { Request } from 'express'; import { Strategy, VerifyCallback } from 'passport-google-oauth20'; import { APP_LOCALES } from 'twenty-shared/translations'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleRequest = Omit< Request, @@ -26,11 +26,11 @@ export type GoogleRequest = Omit< @Injectable() export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { super({ - clientID: environmentService.get('AUTH_GOOGLE_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_GOOGLE_CLIENT_SECRET'), - callbackURL: environmentService.get('AUTH_GOOGLE_CALLBACK_URL'), + clientID: twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_GOOGLE_CLIENT_SECRET'), + callbackURL: twentyConfigService.get('AUTH_GOOGLE_CALLBACK_URL'), scope: ['email', 'profile'], passReqToCallback: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts index 8eea41009f9..012e4483262 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/jwt.auth.strategy.ts @@ -14,8 +14,8 @@ import { AuthContext, JwtPayload, } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -25,7 +25,7 @@ import { ApiKeyWorkspaceEntity } from 'src/modules/api-key/standard-objects/api- @Injectable() export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') { constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly jwtWrapperService: JwtWrapperService, private readonly typeORMService: TypeORMService, private readonly dataSourceService: DataSourceService, diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts index e0be81b2e0b..69d33fc8bb1 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy.ts @@ -4,7 +4,7 @@ import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-microsoft'; import { getMicrosoftApisOauthScopes } from 'src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -16,14 +16,14 @@ export class MicrosoftAPIsOauthCommonStrategy extends PassportStrategy( Strategy, 'microsoft-apis', ) { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { const scopes = getMicrosoftApisOauthScopes(); super({ - clientID: environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_MICROSOFT_CLIENT_SECRET'), + clientID: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_SECRET'), tenant: 'common', - callbackURL: environmentService.get('AUTH_MICROSOFT_APIS_CALLBACK_URL'), + callbackURL: twentyConfigService.get('AUTH_MICROSOFT_APIS_CALLBACK_URL'), scope: scopes, passReqToCallback: true, }); diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts index ef40f331123..c0b9e418fe7 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-exchange-code-for-token.auth.strategy.ts @@ -4,7 +4,7 @@ import { VerifyCallback } from 'passport-google-oauth20'; import { MicrosoftAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy'; import { MicrosoftAPIsRequest } from 'src/engine/core-modules/auth/types/microsoft-api-request.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftAPIScopeConfig = { isCalendarEnabled?: boolean; @@ -12,8 +12,8 @@ export type MicrosoftAPIScopeConfig = { @Injectable() export class MicrosoftAPIsOauthExchangeCodeForTokenStrategy extends MicrosoftAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } async validate( diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts index c0ddea4d4b3..9a48798b647 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft-apis-oauth-request-code.auth.strategy.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { MicrosoftAPIsOauthCommonStrategy } from 'src/engine/core-modules/auth/strategies/microsoft-apis-oauth-common.auth.strategy'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftAPIsOauthRequestCodeStrategy extends MicrosoftAPIsOauthCommonStrategy { - constructor(environmentService: EnvironmentService) { - super(environmentService); + constructor(twentyConfigService: TwentyConfigService) { + super(twentyConfigService); } authenticate(req: any, options: any) { diff --git a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts index 68407499ee8..0c48e37d103 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/strategies/microsoft.auth.strategy.ts @@ -9,7 +9,7 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftRequest = Omit< Request, @@ -29,11 +29,11 @@ export type MicrosoftRequest = Omit< }; export class MicrosoftStrategy extends PassportStrategy(Strategy, 'microsoft') { - constructor(environmentService: EnvironmentService) { + constructor(twentyConfigService: TwentyConfigService) { super({ - clientID: environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), - clientSecret: environmentService.get('AUTH_MICROSOFT_CLIENT_SECRET'), - callbackURL: environmentService.get('AUTH_MICROSOFT_CALLBACK_URL'), + clientID: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), + clientSecret: twentyConfigService.get('AUTH_MICROSOFT_CLIENT_SECRET'), + callbackURL: twentyConfigService.get('AUTH_MICROSOFT_CALLBACK_URL'), tenant: 'common', scope: ['user.read'], passReqToCallback: true, diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts index 5b09e5e0365..2a46f63db96 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.spec.ts @@ -2,16 +2,16 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { Request } from 'express'; -import { Repository } from 'typeorm'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; import { JwtAuthStrategy } from 'src/engine/core-modules/auth/strategies/jwt.auth.strategy'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; import { SSOService } from 'src/engine/core-modules/sso/services/sso.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -22,7 +22,7 @@ import { AccessTokenService } from './access-token.service'; describe('AccessTokenService', () => { let service: AccessTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let userRepository: Repository; let workspaceRepository: Repository; let twentyORMGlobalManager: TwentyORMGlobalManager; @@ -49,7 +49,7 @@ describe('AccessTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -89,7 +89,7 @@ describe('AccessTokenService', () => { service = module.get(AccessTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); userRepository = module.get>( getRepositoryToken(User, 'core'), ); @@ -123,7 +123,7 @@ describe('AccessTokenService', () => { const mockWorkspaceMember = { id: 'workspace-member-id' }; const mockToken = 'mock-token'; - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as User); jest .spyOn(workspaceRepository, 'findOne') @@ -155,7 +155,7 @@ describe('AccessTokenService', () => { }); it('should throw an error if user is not found', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); jest.spyOn(userRepository, 'findOne').mockResolvedValue(null); await expect( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts index 003898b1d36..cd65d2a1f22 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/access-token.service.ts @@ -4,8 +4,8 @@ import { InjectRepository } from '@nestjs/typeorm'; import { addMilliseconds } from 'date-fns'; import { Request } from 'express'; import ms from 'ms'; -import { Repository } from 'typeorm'; import { isWorkspaceActiveOrSuspended } from 'twenty-shared/workspace'; +import { Repository } from 'typeorm'; import { AuthException, @@ -17,8 +17,8 @@ import { AuthContext, JwtPayload, } from 'src/engine/core-modules/auth/types/auth-context.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { userValidator } from 'src/engine/core-modules/user/user.validate'; @@ -32,7 +32,7 @@ export class AccessTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, private readonly jwtStrategy: JwtAuthStrategy, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, @InjectRepository(User, 'core') private readonly userRepository: Repository, @InjectRepository(Workspace, 'core') @@ -46,7 +46,7 @@ export class AccessTokenService { userId: string, workspaceId: string, ): Promise { - const expiresIn = this.environmentService.get('ACCESS_TOKEN_EXPIRES_IN'); + const expiresIn = this.twentyConfigService.get('ACCESS_TOKEN_EXPIRES_IN'); const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts index 1ee9e31e947..13a45ab5514 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.spec.ts @@ -13,14 +13,14 @@ import { EmailVerificationException, EmailVerificationExceptionCode, } from 'src/engine/core-modules/email-verification/email-verification.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { EmailVerificationTokenService } from './email-verification-token.service'; describe('EmailVerificationTokenService', () => { let service: EmailVerificationTokenService; let appTokenRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -31,7 +31,7 @@ describe('EmailVerificationTokenService', () => { useClass: Repository, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -45,7 +45,7 @@ describe('EmailVerificationTokenService', () => { appTokenRepository = module.get>( getRepositoryToken(AppToken, 'core'), ); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); describe('generateToken', () => { @@ -54,7 +54,7 @@ describe('EmailVerificationTokenService', () => { const email = 'test@example.com'; const mockExpiresIn = '24h'; - jest.spyOn(environmentService, 'get').mockReturnValue(mockExpiresIn); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockExpiresIn); jest.spyOn(appTokenRepository, 'create').mockReturnValue({} as AppToken); jest.spyOn(appTokenRepository, 'save').mockResolvedValue({} as AppToken); diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts index 02b6cdb4cd4..3e350726e6c 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/email-verification-token.service.ts @@ -16,18 +16,18 @@ import { EmailVerificationException, EmailVerificationExceptionCode, } from 'src/engine/core-modules/email-verification/email-verification.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class EmailVerificationTokenService { constructor( @InjectRepository(AppToken, 'core') private readonly appTokenRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateToken(userId: string, email: string): Promise { - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'EMAIL_VERIFICATION_TOKEN_EXPIRES_IN', ); const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts index 047958893e4..82343195000 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.spec.ts @@ -1,14 +1,14 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { LoginTokenService } from './login-token.service'; describe('LoginTokenService', () => { let service: LoginTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -24,7 +24,7 @@ describe('LoginTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -34,7 +34,7 @@ describe('LoginTokenService', () => { service = module.get(LoginTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); it('should be defined', () => { @@ -52,7 +52,7 @@ describe('LoginTokenService', () => { jest .spyOn(jwtWrapperService, 'generateAppSecret') .mockReturnValue(mockSecret); - jest.spyOn(environmentService, 'get').mockReturnValue(mockExpiresIn); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockExpiresIn); jest.spyOn(jwtWrapperService, 'sign').mockReturnValue(mockToken); const result = await service.generateLoginToken(email, workspaceId); @@ -65,7 +65,7 @@ describe('LoginTokenService', () => { 'LOGIN', workspaceId, ); - expect(environmentService.get).toHaveBeenCalledWith( + expect(twentyConfigService.get).toHaveBeenCalledWith( 'LOGIN_TOKEN_EXPIRES_IN', ); expect(jwtWrapperService.sign).toHaveBeenCalledWith( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts index a1af3de1ae7..b125393c401 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/login-token.service.ts @@ -4,14 +4,14 @@ import { addMilliseconds } from 'date-fns'; import ms from 'ms'; import { AuthToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class LoginTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateLoginToken( @@ -23,7 +23,7 @@ export class LoginTokenService { workspaceId, ); - const expiresIn = this.environmentService.get('LOGIN_TOKEN_EXPIRES_IN'); + const expiresIn = this.twentyConfigService.get('LOGIN_TOKEN_EXPIRES_IN'); const expiresAt = addMilliseconds(new Date().getTime(), ms(expiresIn)); const jwtPayload = { diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts index a53238067de..6262d08f82e 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.spec.ts @@ -5,8 +5,8 @@ import { Repository } from 'typeorm'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { RefreshTokenService } from './refresh-token.service'; @@ -14,7 +14,7 @@ import { RefreshTokenService } from './refresh-token.service'; describe('RefreshTokenService', () => { let service: RefreshTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let appTokenRepository: Repository; let userRepository: Repository; @@ -32,7 +32,7 @@ describe('RefreshTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -50,7 +50,7 @@ describe('RefreshTokenService', () => { service = module.get(RefreshTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); appTokenRepository = module.get>( getRepositoryToken(AppToken, 'core'), ); @@ -91,7 +91,7 @@ describe('RefreshTokenService', () => { .spyOn(appTokenRepository, 'findOneBy') .mockResolvedValue(mockAppToken as AppToken); jest.spyOn(userRepository, 'findOne').mockResolvedValue(mockUser as User); - jest.spyOn(environmentService, 'get').mockReturnValue('1h'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('1h'); const result = await service.verifyRefreshToken(mockToken); @@ -123,7 +123,7 @@ describe('RefreshTokenService', () => { const mockToken = 'mock-refresh-token'; const mockExpiresIn = '7d'; - jest.spyOn(environmentService, 'get').mockReturnValue(mockExpiresIn); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockExpiresIn); jest .spyOn(jwtWrapperService, 'generateAppSecret') .mockReturnValue('mock-secret'); @@ -153,7 +153,7 @@ describe('RefreshTokenService', () => { }); it('should throw an error if expiration time is not set', async () => { - jest.spyOn(environmentService, 'get').mockReturnValue(undefined); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(undefined); await expect( service.generateRefreshToken('user-id', 'workspace-id'), diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts index ea574709bb9..40172c2e347 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/refresh-token.service.ts @@ -14,15 +14,15 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { AuthToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @Injectable() export class RefreshTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, @InjectRepository(AppToken, 'core') private readonly appTokenRepository: Repository, @InjectRepository(User, 'core') @@ -30,7 +30,7 @@ export class RefreshTokenService { ) {} async verifyRefreshToken(refreshToken: string) { - const coolDown = this.environmentService.get('REFRESH_TOKEN_COOL_DOWN'); + const coolDown = this.twentyConfigService.get('REFRESH_TOKEN_COOL_DOWN'); await this.jwtWrapperService.verifyWorkspaceToken(refreshToken, 'REFRESH'); const jwtPayload = await this.jwtWrapperService.decode(refreshToken); @@ -109,7 +109,7 @@ export class RefreshTokenService { 'REFRESH', workspaceId, ); - const expiresIn = this.environmentService.get('REFRESH_TOKEN_EXPIRES_IN'); + const expiresIn = this.twentyConfigService.get('REFRESH_TOKEN_EXPIRES_IN'); if (!expiresIn) { throw new AuthException( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts index 6add5757a38..4e774a279d9 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.spec.ts @@ -1,14 +1,14 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { TransientTokenService } from './transient-token.service'; describe('TransientTokenService', () => { let service: TransientTokenService; let jwtWrapperService: JwtWrapperService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -24,7 +24,7 @@ describe('TransientTokenService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -34,7 +34,7 @@ describe('TransientTokenService', () => { service = module.get(TransientTokenService); jwtWrapperService = module.get(JwtWrapperService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); it('should be defined', () => { @@ -49,7 +49,7 @@ describe('TransientTokenService', () => { const mockExpiresIn = '15m'; const mockToken = 'mock-token'; - jest.spyOn(environmentService, 'get').mockImplementation((key) => { + jest.spyOn(twentyConfigService, 'get').mockImplementation((key) => { if (key === 'SHORT_TERM_TOKEN_EXPIRES_IN') return mockExpiresIn; return undefined; @@ -66,7 +66,7 @@ describe('TransientTokenService', () => { token: mockToken, expiresAt: expect.any(Date), }); - expect(environmentService.get).toHaveBeenCalledWith( + expect(twentyConfigService.get).toHaveBeenCalledWith( 'SHORT_TERM_TOKEN_EXPIRES_IN', ); expect(jwtWrapperService.sign).toHaveBeenCalledWith( diff --git a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts index 5446193fe92..075ab84169e 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/token/services/transient-token.service.ts @@ -4,14 +4,14 @@ import { addMilliseconds } from 'date-fns'; import ms from 'ms'; import { AuthToken } from 'src/engine/core-modules/auth/dto/token.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class TransientTokenService { constructor( private readonly jwtWrapperService: JwtWrapperService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async generateTransientToken( @@ -23,7 +23,7 @@ export class TransientTokenService { 'LOGIN', workspaceId, ); - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'SHORT_TERM_TOKEN_EXPIRES_IN', ); diff --git a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts index 78023175f9d..f690682b0da 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-feature-used.listener.ts @@ -6,21 +6,21 @@ import { OnCustomBatchEvent } from 'src/engine/api/graphql/graphql-query-runner/ import { BILLING_FEATURE_USED } from 'src/engine/core-modules/billing/constants/billing-feature-used.constant'; import { BillingUsageService } from 'src/engine/core-modules/billing/services/billing-usage.service'; import { BillingUsageEvent } from 'src/engine/core-modules/billing/types/billing-usage-event.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; @Injectable() export class BillingFeatureUsedListener { constructor( private readonly billingUsageService: BillingUsageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} @OnCustomBatchEvent(BILLING_FEATURE_USED) async handleBillingFeatureUsedEvent( payload: WorkspaceEventBatch, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } diff --git a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts index 28b030fb439..328135c0c34 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/listeners/billing-workspace-member.listener.ts @@ -8,11 +8,11 @@ import { UpdateSubscriptionQuantityJob, UpdateSubscriptionQuantityJobData, } from 'src/engine/core-modules/billing/jobs/update-subscription-quantity.job'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -21,7 +21,7 @@ export class BillingWorkspaceMemberListener { constructor( @InjectMessageQueue(MessageQueue.billingQueue) private readonly messageQueueService: MessageQueueService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} @OnDatabaseBatchEvent('workspaceMember', DatabaseEventAction.CREATED) @@ -31,7 +31,7 @@ export class BillingWorkspaceMemberListener { ObjectRecordCreateEvent >, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts index 0287ee3a96b..ece0de3dc46 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts @@ -17,7 +17,7 @@ import { BillingSubscriptionItemService } from 'src/engine/core-modules/billing/ import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { StripeBillingMeterEventService } from 'src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service'; import { BillingUsageEvent } from 'src/engine/core-modules/billing/types/billing-usage-event.type'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Injectable() @@ -28,12 +28,12 @@ export class BillingUsageService { private readonly billingCustomerRepository: Repository, private readonly billingSubscriptionService: BillingSubscriptionService, private readonly stripeBillingMeterEventService: StripeBillingMeterEventService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly billingSubscriptionItemService: BillingSubscriptionItemService, ) {} async canFeatureBeUsed(workspaceId: string): Promise { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return true; } diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts index 2ec8dc157cd..b024edf9d84 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing.service.ts @@ -13,15 +13,15 @@ import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/billin import { BillingProductService } from 'src/engine/core-modules/billing/services/billing-product.service'; import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { getPlanKeyFromSubscription } from 'src/engine/core-modules/billing/utils/get-plan-key-from-subscription.util'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class BillingService { protected readonly logger = new Logger(BillingService.name); constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly billingSubscriptionService: BillingSubscriptionService, private readonly billingProductService: BillingProductService, private readonly featureFlagService: FeatureFlagService, @@ -30,7 +30,7 @@ export class BillingService { ) {} isBillingEnabled() { - return this.environmentService.get('IS_BILLING_ENABLED'); + return this.twentyConfigService.get('IS_BILLING_ENABLED'); } async hasWorkspaceAnySubscription(workspaceId: string) { diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts index 1b812b9a0d3..90d9f460491 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter-event.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { BillingMeterEventName } from 'src/engine/core-modules/billing/enums/billing-meter-event-names'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeBillingMeterEventService { @@ -14,14 +14,14 @@ export class StripeBillingMeterEventService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts index 7900db366f7..7ed9f1a5e2a 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-meter.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeBillingMeterService { @@ -13,14 +13,14 @@ export class StripeBillingMeterService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts index dabd0eaad29..c1302b1f36e 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-billing-portal.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeBillingPortalService { @@ -14,15 +14,15 @@ export class StripeBillingPortalService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts index e143aa43d1c..ebe55ef16a0 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-checkout.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { BillingPlanKey } from 'src/engine/core-modules/billing/enums/billing-plan-key.enum'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @Injectable() @@ -15,14 +15,14 @@ export class StripeCheckoutService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } @@ -57,7 +57,7 @@ export class StripeCheckoutService { }, ...(withTrialPeriod ? { - trial_period_days: this.environmentService.get( + trial_period_days: this.twentyConfigService.get( requirePaymentMethod ? 'BILLING_FREE_TRIAL_WITH_CREDIT_CARD_DURATION_IN_DAYS' : 'BILLING_FREE_TRIAL_WITHOUT_CREDIT_CARD_DURATION_IN_DAYS', diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts index 0e500862d97..c6c62caa9c6 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-customer.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeCustomerService { @@ -13,14 +13,14 @@ export class StripeCustomerService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts index 877516913fa..a8e889d91b1 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-price.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripePriceService { @@ -13,14 +13,14 @@ export class StripePriceService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts index ff9ee6c4494..ca2a4c980b1 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-product.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeProductService { @@ -13,14 +13,14 @@ export class StripeProductService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts index 1f7a40b4099..403da680f87 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription-item.service.ts @@ -5,7 +5,7 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeSubscriptionItemService { @@ -13,14 +13,14 @@ export class StripeSubscriptionItemService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts index 60df5eebeb7..ae72d1cc501 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-subscription.service.ts @@ -6,7 +6,7 @@ import Stripe from 'stripe'; import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeSubscriptionService { @@ -14,14 +14,14 @@ export class StripeSubscriptionService { private readonly stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } diff --git a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts index 88e0977b85b..23649f366c6 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/stripe/services/stripe-webhook.service.ts @@ -5,26 +5,26 @@ import { Injectable, Logger } from '@nestjs/common'; import Stripe from 'stripe'; import { StripeSDKService } from 'src/engine/core-modules/billing/stripe/stripe-sdk/services/stripe-sdk.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class StripeWebhookService { protected readonly logger = new Logger(StripeWebhookService.name); private stripe: Stripe; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly stripeSDKService: StripeSDKService, ) { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } this.stripe = this.stripeSDKService.getStripe( - this.environmentService.get('BILLING_STRIPE_API_KEY'), + this.twentyConfigService.get('BILLING_STRIPE_API_KEY'), ); } constructEventFromPayload(signature: string, payload: Buffer) { - const webhookSecret = this.environmentService.get( + const webhookSecret = this.twentyConfigService.get( 'BILLING_STRIPE_WEBHOOK_SECRET', ); diff --git a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts index 7a84d95c348..afc1f4be72c 100644 --- a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module-factory.ts @@ -3,13 +3,13 @@ import { CacheModuleOptions } from '@nestjs/common'; import { redisStore } from 'cache-manager-redis-yet'; import { CacheStorageType } from 'src/engine/core-modules/cache-storage/types/cache-storage-type.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const cacheStorageModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): CacheModuleOptions => { const cacheStorageType = CacheStorageType.Redis; - const cacheStorageTtl = environmentService.get('CACHE_STORAGE_TTL'); + const cacheStorageTtl = twentyConfigService.get('CACHE_STORAGE_TTL'); const cacheModuleOptions: CacheModuleOptions = { isGlobal: true, ttl: cacheStorageTtl * 1000, @@ -20,7 +20,7 @@ export const cacheStorageModuleFactory = ( return cacheModuleOptions; }*/ case CacheStorageType.Redis: { - const redisUrl = environmentService.get('REDIS_URL'); + const redisUrl = twentyConfigService.get('REDIS_URL'); if (!redisUrl) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts index 3f12d09e6d9..96210df65f9 100644 --- a/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts +++ b/packages/twenty-server/src/engine/core-modules/cache-storage/cache-storage.module.ts @@ -6,7 +6,7 @@ import { cacheStorageModuleFactory } from 'src/engine/core-modules/cache-storage import { FlushCacheCommand } from 'src/engine/core-modules/cache-storage/commands/flush-cache.command'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Global() @Module({ @@ -15,7 +15,7 @@ import { EnvironmentService } from 'src/engine/core-modules/environment/environm isGlobal: true, imports: [ConfigModule], useFactory: cacheStorageModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), ], providers: [ diff --git a/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts index c6a1e4c23ed..622e9c979ad 100644 --- a/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/captcha/captcha.module-factory.ts @@ -2,14 +2,14 @@ import { CaptchaDriverOptions, CaptchaModuleOptions, } from 'src/engine/core-modules/captcha/interfaces'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const captchaModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): CaptchaModuleOptions | undefined => { - const driver = environmentService.get('CAPTCHA_DRIVER'); - const siteKey = environmentService.get('CAPTCHA_SITE_KEY'); - const secretKey = environmentService.get('CAPTCHA_SECRET_KEY'); + const driver = twentyConfigService.get('CAPTCHA_DRIVER'); + const siteKey = twentyConfigService.get('CAPTCHA_SITE_KEY'); + const secretKey = twentyConfigService.get('CAPTCHA_SECRET_KEY'); if (!driver) { return; diff --git a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts index fdca070c879..e67b141c0c8 100644 --- a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ClientConfigResolver } from './client-config.resolver'; @@ -13,7 +13,7 @@ describe('ClientConfigResolver', () => { providers: [ ClientConfigResolver, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, { diff --git a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts index 30fc67cfb18..b230c550a64 100644 --- a/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/client-config/client-config.resolver.ts @@ -1,17 +1,17 @@ import { Query, Resolver } from '@nestjs/graphql'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { PUBLIC_FEATURE_FLAGS } from 'src/engine/core-modules/feature-flag/constants/public-feature-flag.const'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ClientConfig } from './client-config.entity'; @Resolver() export class ClientConfigResolver { constructor( - private environmentService: EnvironmentService, + private twentyConfigService: TwentyConfigService, private domainManagerService: DomainManagerService, ) {} @@ -19,17 +19,17 @@ export class ClientConfigResolver { async clientConfig(): Promise { const clientConfig: ClientConfig = { billing: { - isBillingEnabled: this.environmentService.get('IS_BILLING_ENABLED'), - billingUrl: this.environmentService.get('BILLING_PLAN_REQUIRED_LINK'), + isBillingEnabled: this.twentyConfigService.get('IS_BILLING_ENABLED'), + billingUrl: this.twentyConfigService.get('BILLING_PLAN_REQUIRED_LINK'), trialPeriods: [ { - duration: this.environmentService.get( + duration: this.twentyConfigService.get( 'BILLING_FREE_TRIAL_WITH_CREDIT_CARD_DURATION_IN_DAYS', ), isCreditCardRequired: true, }, { - duration: this.environmentService.get( + duration: this.twentyConfigService.get( 'BILLING_FREE_TRIAL_WITHOUT_CREDIT_CARD_DURATION_IN_DAYS', ), isCreditCardRequired: false, @@ -37,63 +37,64 @@ export class ClientConfigResolver { ], }, authProviders: { - google: this.environmentService.get('AUTH_GOOGLE_ENABLED'), + google: this.twentyConfigService.get('AUTH_GOOGLE_ENABLED'), magicLink: false, - password: this.environmentService.get('AUTH_PASSWORD_ENABLED'), - microsoft: this.environmentService.get('AUTH_MICROSOFT_ENABLED'), + password: this.twentyConfigService.get('AUTH_PASSWORD_ENABLED'), + microsoft: this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED'), sso: [], }, - signInPrefilled: this.environmentService.get('SIGN_IN_PREFILLED'), - isMultiWorkspaceEnabled: this.environmentService.get( + signInPrefilled: this.twentyConfigService.get('SIGN_IN_PREFILLED'), + isMultiWorkspaceEnabled: this.twentyConfigService.get( 'IS_MULTIWORKSPACE_ENABLED', ), - isEmailVerificationRequired: this.environmentService.get( + isEmailVerificationRequired: this.twentyConfigService.get( 'IS_EMAIL_VERIFICATION_REQUIRED', ), - defaultSubdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + defaultSubdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), frontDomain: this.domainManagerService.getFrontUrl().hostname, debugMode: - this.environmentService.get('NODE_ENV') === NodeEnvironment.development, + this.twentyConfigService.get('NODE_ENV') === + NodeEnvironment.development, support: { - supportDriver: this.environmentService.get('SUPPORT_DRIVER'), - supportFrontChatId: this.environmentService.get( + supportDriver: this.twentyConfigService.get('SUPPORT_DRIVER'), + supportFrontChatId: this.twentyConfigService.get( 'SUPPORT_FRONT_CHAT_ID', ), }, sentry: { - environment: this.environmentService.get('SENTRY_ENVIRONMENT'), - release: this.environmentService.get('SENTRY_RELEASE'), - dsn: this.environmentService.get('SENTRY_FRONT_DSN'), + environment: this.twentyConfigService.get('SENTRY_ENVIRONMENT'), + release: this.twentyConfigService.get('SENTRY_RELEASE'), + dsn: this.twentyConfigService.get('SENTRY_FRONT_DSN'), }, captcha: { - provider: this.environmentService.get('CAPTCHA_DRIVER'), - siteKey: this.environmentService.get('CAPTCHA_SITE_KEY'), + provider: this.twentyConfigService.get('CAPTCHA_DRIVER'), + siteKey: this.twentyConfigService.get('CAPTCHA_SITE_KEY'), }, - chromeExtensionId: this.environmentService.get('CHROME_EXTENSION_ID'), + chromeExtensionId: this.twentyConfigService.get('CHROME_EXTENSION_ID'), api: { - mutationMaximumAffectedRecords: this.environmentService.get( + mutationMaximumAffectedRecords: this.twentyConfigService.get( 'MUTATION_MAXIMUM_AFFECTED_RECORDS', ), }, - isAttachmentPreviewEnabled: this.environmentService.get( + isAttachmentPreviewEnabled: this.twentyConfigService.get( 'IS_ATTACHMENT_PREVIEW_ENABLED', ), - analyticsEnabled: this.environmentService.get('ANALYTICS_ENABLED'), + analyticsEnabled: this.twentyConfigService.get('ANALYTICS_ENABLED'), canManageFeatureFlags: - this.environmentService.get('NODE_ENV') === + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development || - this.environmentService.get('IS_BILLING_ENABLED'), + this.twentyConfigService.get('IS_BILLING_ENABLED'), publicFeatureFlags: PUBLIC_FEATURE_FLAGS, - isMicrosoftMessagingEnabled: this.environmentService.get( + isMicrosoftMessagingEnabled: this.twentyConfigService.get( 'MESSAGING_PROVIDER_MICROSOFT_ENABLED', ), - isMicrosoftCalendarEnabled: this.environmentService.get( + isMicrosoftCalendarEnabled: this.twentyConfigService.get( 'CALENDAR_PROVIDER_MICROSOFT_ENABLED', ), - isGoogleMessagingEnabled: this.environmentService.get( + isGoogleMessagingEnabled: this.twentyConfigService.get( 'MESSAGING_PROVIDER_GMAIL_ENABLED', ), - isGoogleCalendarEnabled: this.environmentService.get( + isGoogleCalendarEnabled: this.twentyConfigService.get( 'CALENDAR_PROVIDER_GOOGLE_ENABLED', ), }; diff --git a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts index fcbf7cc19c7..15e6160856d 100644 --- a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts +++ b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts @@ -14,8 +14,6 @@ import { CaptchaModule } from 'src/engine/core-modules/captcha/captcha.module'; import { captchaModuleFactory } from 'src/engine/core-modules/captcha/captcha.module-factory'; import { EmailModule } from 'src/engine/core-modules/email/email.module'; import { emailModuleFactory } from 'src/engine/core-modules/email/email.module-factory'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerModule } from 'src/engine/core-modules/exception-handler/exception-handler.module'; import { exceptionHandlerModuleFactory } from 'src/engine/core-modules/exception-handler/exception-handler.module-factory'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; @@ -42,6 +40,8 @@ import { serverlessModuleFactory } from 'src/engine/core-modules/serverless/serv import { ServerlessModule } from 'src/engine/core-modules/serverless/serverless.module'; import { WorkspaceSSOModule } from 'src/engine/core-modules/sso/sso.module'; import { TelemetryModule } from 'src/engine/core-modules/telemetry/telemetry.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserModule } from 'src/engine/core-modules/user/user.module'; import { WorkflowApiModule } from 'src/engine/core-modules/workflow/workflow-api.module'; import { WorkspaceInvitationModule } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.module'; @@ -79,31 +79,31 @@ import { FileModule } from './file/file.module'; AdminPanelModule, LabModule, RoleModule, - EnvironmentModule.forRoot({}), + TwentyConfigModule, RedisClientModule, FileStorageModule.forRootAsync({ useFactory: fileStorageModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), LoggerModule.forRootAsync({ useFactory: loggerModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), MessageQueueModule.registerAsync({ useFactory: messageQueueModuleFactory, - inject: [EnvironmentService, RedisClientService], + inject: [TwentyConfigService, RedisClientService], }), ExceptionHandlerModule.forRootAsync({ useFactory: exceptionHandlerModuleFactory, - inject: [EnvironmentService, HttpAdapterHost], + inject: [TwentyConfigService, HttpAdapterHost], }), EmailModule.forRoot({ useFactory: emailModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), CaptchaModule.forRoot({ useFactory: captchaModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), EventEmitterModule.forRoot({ wildcard: true, @@ -111,15 +111,15 @@ import { FileModule } from './file/file.module'; CacheStorageModule, LLMChatModelModule.forRoot({ useFactory: llmChatModelModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), LLMTracingModule.forRoot({ useFactory: llmTracingModuleFactory, - inject: [EnvironmentService], + inject: [TwentyConfigService], }), ServerlessModule.forRootAsync({ useFactory: serverlessModuleFactory, - inject: [EnvironmentService, FileStorageService], + inject: [TwentyConfigService, FileStorageService], }), SearchModule, ], diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts index fe847fb0500..9ed483f30b3 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/controllers/cloudflare.spec.ts @@ -1,22 +1,22 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; import { Request, Response } from 'express'; +import { Repository } from 'typeorm'; import { CloudflareController } from 'src/engine/core-modules/domain-manager/controllers/cloudflare.controller'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service'; import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager/dtos/custom-domain-valid-records'; import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; describe('CloudflareController - customHostnameWebhooks', () => { let controller: CloudflareController; let WorkspaceRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; let customDomainService: CustomDomainService; @@ -56,7 +56,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -66,7 +66,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { controller = module.get(CloudflareController); WorkspaceRepository = module.get(getRepositoryToken(Workspace, 'core')); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); customDomainService = module.get(CustomDomainService); @@ -83,7 +83,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); await controller.customHostnameWebhooks(req, res); @@ -102,7 +102,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); jest .spyOn(customDomainService, 'getCustomDomainDetails') .mockResolvedValue({ @@ -147,7 +147,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); jest.spyOn(WorkspaceRepository, 'findOneBy').mockResolvedValue({ customDomain: 'notfound.com', isCustomDomainEnabled: true, @@ -180,7 +180,7 @@ describe('CloudflareController - customHostnameWebhooks', () => { send: sendMock, } as unknown as Response; - jest.spyOn(environmentService, 'get').mockReturnValue('correct-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('correct-secret'); jest.spyOn(WorkspaceRepository, 'findOneBy').mockResolvedValue({ customDomain: 'nothing-change.com', isCustomDomainEnabled: true, diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts index 62d6b33bd6a..f6f88c95e0b 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.guard.ts @@ -4,17 +4,17 @@ import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { timingSafeEqual } from 'crypto'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class CloudflareSecretMatchGuard implements CanActivate { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} canActivate(context: ExecutionContext): boolean { try { const request = context.switchToHttp().getRequest(); - const cloudflareWebhookSecret = this.environmentService.get( + const cloudflareWebhookSecret = this.twentyConfigService.get( 'CLOUDFLARE_WEBHOOK_SECRET', ); diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts index 75c4a5db26c..0c2815097c1 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/guards/cloudflare-secret.spec.ts @@ -2,25 +2,25 @@ import { ExecutionContext } from '@nestjs/common'; import * as crypto from 'crypto'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { CloudflareSecretMatchGuard } from './cloudflare-secret.guard'; describe('CloudflareSecretMatchGuard.canActivate', () => { let guard: CloudflareSecretMatchGuard; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(() => { - environmentService = { + twentyConfigService = { get: jest.fn(), - } as unknown as EnvironmentService; - guard = new CloudflareSecretMatchGuard(environmentService); + } as unknown as TwentyConfigService; + guard = new CloudflareSecretMatchGuard(twentyConfigService); }); it('should return true when the webhook secret matches', () => { const mockRequest = { headers: { 'cf-webhook-auth': 'valid-secret' } }; - jest.spyOn(environmentService, 'get').mockReturnValue('valid-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('valid-secret'); const mockContext = { switchToHttp: () => ({ @@ -36,7 +36,7 @@ describe('CloudflareSecretMatchGuard.canActivate', () => { it('should return true when env is not set', () => { const mockRequest = { headers: { 'cf-webhook-auth': 'valid-secret' } }; - jest.spyOn(environmentService, 'get').mockReturnValue(undefined); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(undefined); const mockContext = { switchToHttp: () => ({ @@ -52,7 +52,7 @@ describe('CloudflareSecretMatchGuard.canActivate', () => { it('should return false if an error occurs', () => { const mockRequest = { headers: {} }; - jest.spyOn(environmentService, 'get').mockReturnValue('valid-secret'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('valid-secret'); const mockContext = { switchToHttp: () => ({ diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts index 69b0a16b43d..dbfaaa9bce2 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.spec.ts @@ -1,18 +1,18 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { CustomHostnameCreateResponse } from 'cloudflare/resources/custom-hostnames/custom-hostnames'; import Cloudflare from 'cloudflare'; +import { CustomHostnameCreateResponse } from 'cloudflare/resources/custom-hostnames/custom-hostnames'; +import { DomainManagerException } from 'src/engine/core-modules/domain-manager/domain-manager.exception'; import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { DomainManagerException } from 'src/engine/core-modules/domain-manager/domain-manager.exception'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; jest.mock('cloudflare'); describe('CustomDomainService', () => { let customDomainService: CustomDomainService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let domainManagerService: DomainManagerService; beforeEach(async () => { @@ -20,7 +20,7 @@ describe('CustomDomainService', () => { providers: [ CustomDomainService, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -35,7 +35,7 @@ describe('CustomDomainService', () => { }).compile(); customDomainService = module.get(CustomDomainService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); domainManagerService = module.get(DomainManagerService); @@ -52,11 +52,11 @@ describe('CustomDomainService', () => { it('should initialize cloudflareClient when CLOUDFLARE_API_KEY is defined', () => { const mockApiKey = 'test-api-key'; - jest.spyOn(environmentService, 'get').mockReturnValue(mockApiKey); + jest.spyOn(twentyConfigService, 'get').mockReturnValue(mockApiKey); - const instance = new CustomDomainService(environmentService, {} as any); + const instance = new CustomDomainService(twentyConfigService, {} as any); - expect(environmentService.get).toHaveBeenCalledWith('CLOUDFLARE_API_KEY'); + expect(twentyConfigService.get).toHaveBeenCalledWith('CLOUDFLARE_API_KEY'); expect(Cloudflare).toHaveBeenCalledWith({ apiToken: mockApiKey }); expect(instance.cloudflareClient).toBeDefined(); }); @@ -89,7 +89,7 @@ describe('CustomDomainService', () => { jest .spyOn(customDomainService, 'getCustomDomainDetails') .mockResolvedValueOnce(undefined); - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; await customDomainService.registerCustomDomain(customDomain); @@ -111,7 +111,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; const result = @@ -137,7 +137,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); jest .spyOn(domainManagerService, 'getFrontUrl') @@ -175,7 +175,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); jest .spyOn(domainManagerService, 'getFrontUrl') .mockReturnValue(new URL('https://front.domain')); @@ -199,7 +199,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; await expect( @@ -249,7 +249,7 @@ describe('CustomDomainService', () => { }, }; - jest.spyOn(environmentService, 'get').mockReturnValue('test-zone-id'); + jest.spyOn(twentyConfigService, 'get').mockReturnValue('test-zone-id'); (customDomainService as any).cloudflareClient = cloudflareMock; await expect( diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts index bca196fa367..56787244ed5 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/custom-domain.service.ts @@ -9,21 +9,21 @@ import { DomainManagerExceptionCode, } from 'src/engine/core-modules/domain-manager/domain-manager.exception'; import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager/dtos/custom-domain-valid-records'; -import { domainManagerValidator } from 'src/engine/core-modules/domain-manager/validator/cloudflare.validate'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { domainManagerValidator } from 'src/engine/core-modules/domain-manager/validator/cloudflare.validate'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class CustomDomainService { cloudflareClient?: Cloudflare; constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, ) { - if (this.environmentService.get('CLOUDFLARE_API_KEY')) { + if (this.twentyConfigService.get('CLOUDFLARE_API_KEY')) { this.cloudflareClient = new Cloudflare({ - apiToken: this.environmentService.get('CLOUDFLARE_API_KEY'), + apiToken: this.twentyConfigService.get('CLOUDFLARE_API_KEY'), }); } } @@ -39,7 +39,7 @@ export class CustomDomainService { } return await this.cloudflareClient.customHostnames.create({ - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), hostname: customDomain, ssl: { method: 'txt', @@ -63,7 +63,7 @@ export class CustomDomainService { domainManagerValidator.isCloudflareInstanceDefined(this.cloudflareClient); const response = await this.cloudflareClient.customHostnames.list({ - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), hostname: customDomain, }); @@ -163,7 +163,7 @@ export class CustomDomainService { if (customHostname) { await this.cloudflareClient.customHostnames.delete(customHostname.id, { - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), }); } } catch (err) { @@ -175,7 +175,7 @@ export class CustomDomainService { domainManagerValidator.isCloudflareInstanceDefined(this.cloudflareClient); await this.cloudflareClient.customHostnames.delete(customHostnameId, { - zone_id: this.environmentService.get('CLOUDFLARE_ZONE_ID'), + zone_id: this.twentyConfigService.get('CLOUDFLARE_ZONE_ID'), }); } diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts index d39d05ab751..73c0c1d5e62 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DomainManagerService } from './domain-manager.service'; @@ -12,7 +12,7 @@ describe('DomainManagerService', () => { describe('getWorkspaceUrls', () => { it('should return a URL containing the correct customDomain if customDomain is provided', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -35,7 +35,7 @@ describe('DomainManagerService', () => { it('should return a URL containing the correct subdomain if customDomain is not provided but subdomain is', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -58,7 +58,7 @@ describe('DomainManagerService', () => { }); }); let domainManagerService: DomainManagerService; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -69,7 +69,7 @@ describe('DomainManagerService', () => { useClass: Repository, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -79,13 +79,13 @@ describe('DomainManagerService', () => { domainManagerService = module.get(DomainManagerService); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); }); describe('buildBaseUrl', () => { it('should build the base URL from environment variables', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -101,7 +101,7 @@ describe('DomainManagerService', () => { it('should append default subdomain if multiworkspace is enabled', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -121,7 +121,7 @@ describe('DomainManagerService', () => { describe('buildWorkspaceURL', () => { it('should build workspace URL with given subdomain', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -145,7 +145,7 @@ describe('DomainManagerService', () => { it('should set the pathname if provided', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', @@ -168,7 +168,7 @@ describe('DomainManagerService', () => { it('should set the search parameters if provided', () => { jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockImplementation((key: string) => { const env = { FRONTEND_URL: 'https://example.com', diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts index 22b2103eb36..5696b732f0e 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/services/domain-manager.service.ts @@ -10,7 +10,7 @@ import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager import { generateRandomSubdomain } from 'src/engine/core-modules/domain-manager/utils/generate-random-subdomain'; import { getSubdomainFromEmail } from 'src/engine/core-modules/domain-manager/utils/get-subdomain-from-email'; import { getSubdomainNameFromDisplayName } from 'src/engine/core-modules/domain-manager/utils/get-subdomain-name-from-display-name'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate'; @@ -19,13 +19,13 @@ export class DomainManagerService { constructor( @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} getFrontUrl() { return new URL( - this.environmentService.get('FRONTEND_URL') ?? - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('FRONTEND_URL') ?? + this.twentyConfigService.get('SERVER_URL'), ); } @@ -33,10 +33,10 @@ export class DomainManagerService { const baseUrl = this.getFrontUrl(); if ( - this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') && - this.environmentService.get('DEFAULT_SUBDOMAIN') + this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED') && + this.twentyConfigService.get('DEFAULT_SUBDOMAIN') ) { - baseUrl.hostname = `${this.environmentService.get('DEFAULT_SUBDOMAIN')}.${baseUrl.hostname}`; + baseUrl.hostname = `${this.twentyConfigService.get('DEFAULT_SUBDOMAIN')}.${baseUrl.hostname}`; } return baseUrl; @@ -122,7 +122,7 @@ export class DomainManagerService { } isDefaultSubdomain(subdomain: string) { - return subdomain === this.environmentService.get('DEFAULT_SUBDOMAIN'); + return subdomain === this.twentyConfigService.get('DEFAULT_SUBDOMAIN'); } computeRedirectErrorUrl( @@ -139,7 +139,7 @@ export class DomainManagerService { } private async getDefaultWorkspace() { - if (this.environmentService.get('IS_MULTIWORKSPACE_ENABLED')) { + if (this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED')) { throw new Error( 'Default workspace does not exist when multi-workspace is enabled', ); @@ -171,7 +171,7 @@ export class DomainManagerService { } async getWorkspaceByOriginOrDefaultWorkspace(origin: string) { - if (!this.environmentService.get('IS_MULTIWORKSPACE_ENABLED')) { + if (!this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED')) { return this.getDefaultWorkspace(); } @@ -222,7 +222,7 @@ export class DomainManagerService { private getTwentyWorkspaceUrl(subdomain: string) { const url = this.getFrontUrl(); - url.hostname = this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') + url.hostname = this.twentyConfigService.get('IS_MULTIWORKSPACE_ENABLED') ? `${subdomain}.${url.hostname}` : url.hostname; @@ -234,7 +234,7 @@ export class DomainManagerService { ) { if (!workspace) { return { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }; } diff --git a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts index 233dcb1f39d..c22faf26cf9 100644 --- a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts +++ b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.module.ts @@ -7,7 +7,7 @@ import { DomainManagerModule } from 'src/engine/core-modules/domain-manager/doma import { EmailVerificationResolver } from 'src/engine/core-modules/email-verification/email-verification.resolver'; import { EmailVerificationService } from 'src/engine/core-modules/email-verification/services/email-verification.service'; import { EmailModule } from 'src/engine/core-modules/email/email.module'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module'; import { UserModule } from 'src/engine/core-modules/user/user.module'; @@ -15,7 +15,7 @@ import { UserModule } from 'src/engine/core-modules/user/user.module'; imports: [ TypeOrmModule.forFeature([AppToken], 'core'), EmailModule, - EnvironmentModule, + TwentyConfigModule, DomainManagerModule, UserModule, UserWorkspaceModule, diff --git a/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts b/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts index d94198b783c..b8496754315 100644 --- a/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts +++ b/packages/twenty-server/src/engine/core-modules/email-verification/services/email-verification.service.ts @@ -22,7 +22,7 @@ import { EmailVerificationExceptionCode, } from 'src/engine/core-modules/email-verification/email-verification.exception'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @Injectable() @@ -33,7 +33,7 @@ export class EmailVerificationService { private readonly appTokenRepository: Repository, private readonly domainManagerService: DomainManagerService, private readonly emailService: EmailService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly userService: UserService, private readonly emailVerificationTokenService: EmailVerificationTokenService, ) {} @@ -46,7 +46,7 @@ export class EmailVerificationService { | undefined, locale: keyof typeof APP_LOCALES, ) { - if (!this.environmentService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { + if (!this.twentyConfigService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { return { success: false }; } @@ -79,9 +79,9 @@ export class EmailVerificationService { i18n.activate(locale); await this.emailService.send({ - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: email, subject: t`Welcome to Twenty: Please Confirm Your Email`, text, @@ -98,7 +98,7 @@ export class EmailVerificationService { | undefined, locale: keyof typeof APP_LOCALES, ) { - if (!this.environmentService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { + if (!this.twentyConfigService.get('IS_EMAIL_VERIFICATION_REQUIRED')) { throw new EmailVerificationException( 'Email verification token cannot be sent because email verification is not required', EmailVerificationExceptionCode.EMAIL_VERIFICATION_NOT_REQUIRED, diff --git a/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts b/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts index fba35247111..690433bf220 100644 --- a/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/email/email.module-factory.ts @@ -3,12 +3,12 @@ import { EmailModuleOptions, } from 'src/engine/core-modules/email/interfaces/email.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const emailModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): EmailModuleOptions => { - const driver = environmentService.get('EMAIL_DRIVER'); + const driver = twentyConfigService.get('EMAIL_DRIVER'); switch (driver) { case EmailDriver.Logger: @@ -21,11 +21,11 @@ export const emailModuleFactory = ( type: EmailDriver.Smtp, }; - const host = environmentService.get('EMAIL_SMTP_HOST'); - const port = environmentService.get('EMAIL_SMTP_PORT'); - const user = environmentService.get('EMAIL_SMTP_USER'); - const pass = environmentService.get('EMAIL_SMTP_PASSWORD'); - const noTLS = environmentService.get('EMAIL_SMTP_NO_TLS'); + const host = twentyConfigService.get('EMAIL_SMTP_HOST'); + const port = twentyConfigService.get('EMAIL_SMTP_PORT'); + const user = twentyConfigService.get('EMAIL_SMTP_USER'); + const pass = twentyConfigService.get('EMAIL_SMTP_PASSWORD'); + const noTLS = twentyConfigService.get('EMAIL_SMTP_NO_TLS'); if (!host || !port) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts deleted file mode 100644 index 121f5326113..00000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/__tests__/environment-variables-group-metadata.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ENVIRONMENT_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/environment/constants/environment-variables-group-metadata'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; - -describe('ENVIRONMENT_VARIABLES_GROUP_METADATA', () => { - it('should include all EnvironmentVariablesGroup enum values', () => { - const enumValues = Object.values(EnvironmentVariablesGroup); - const metadataKeys = Object.keys(ENVIRONMENT_VARIABLES_GROUP_METADATA); - - enumValues.forEach((enumValue) => { - expect(metadataKeys).toContain(enumValue); - }); - - metadataKeys.forEach((key) => { - expect(enumValues).toContain(key); - }); - - expect(enumValues.length).toBe(metadataKeys.length); - }); - - it('should have unique position values', () => { - const positions = Object.values(ENVIRONMENT_VARIABLES_GROUP_METADATA).map( - (metadata) => metadata.position, - ); - const uniquePositions = new Set(positions); - - expect(positions.length).toBe(uniquePositions.size); - }); -}); diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts deleted file mode 100644 index 4b0d9a848de..00000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-masking-config.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; - -type LastNCharsConfig = { - strategy: EnvironmentVariablesMaskingStrategies.LAST_N_CHARS; - chars: number; -}; - -type HidePasswordConfig = { - strategy: EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD; -}; - -type MaskingConfigType = { - APP_SECRET: LastNCharsConfig; - PG_DATABASE_URL: HidePasswordConfig; - REDIS_URL: HidePasswordConfig; -}; - -export const ENVIRONMENT_VARIABLES_MASKING_CONFIG: MaskingConfigType = { - APP_SECRET: { - strategy: EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, - chars: 5, - }, - PG_DATABASE_URL: { - strategy: EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, - }, - REDIS_URL: { - strategy: EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, - }, -} as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts deleted file mode 100644 index a1249e47127..00000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-key.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const ENVIRONMENT_VARIABLES_METADATA_DECORATOR_KEY = - 'environment-variables-metadata' as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts b/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts deleted file mode 100644 index aa1c0c378eb..00000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-metadata-decorator-names-key.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const ENVIRONMENT_VARIABLES_METADATA_DECORATOR_NAMES_KEY = - 'environment-variable-names' as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts b/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts deleted file mode 100644 index c0a9158bf98..00000000000 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.service.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { Injectable } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -import { ENVIRONMENT_VARIABLES_MASKING_CONFIG } from 'src/engine/core-modules/environment/constants/environment-variables-masking-config'; -import { EnvironmentVariablesMetadataOptions } from 'src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator'; -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; -import { EnvironmentVariables } from 'src/engine/core-modules/environment/environment-variables'; -import { environmentVariableMaskSensitiveData } from 'src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util'; -import { TypedReflect } from 'src/utils/typed-reflect'; - -@Injectable() -export class EnvironmentService { - constructor(private readonly configService: ConfigService) {} - - get(key: T): EnvironmentVariables[T] { - return this.configService.get( - key, - new EnvironmentVariables()[key], - ); - } - - getAll(): Record< - string, - { - value: EnvironmentVariables[keyof EnvironmentVariables]; - metadata: EnvironmentVariablesMetadataOptions; - } - > { - const result: Record< - string, - { - value: EnvironmentVariables[keyof EnvironmentVariables]; - metadata: EnvironmentVariablesMetadataOptions; - } - > = {}; - - const envVars = new EnvironmentVariables(); - const metadata = - TypedReflect.getMetadata('environment-variables', EnvironmentVariables) ?? - {}; - - Object.entries(metadata).forEach(([key, envMetadata]) => { - let value = - this.configService.get(key) ?? - envVars[key as keyof EnvironmentVariables] ?? - ''; - - if ( - typeof value === 'string' && - key in ENVIRONMENT_VARIABLES_MASKING_CONFIG - ) { - const varMaskingConfig = - ENVIRONMENT_VARIABLES_MASKING_CONFIG[ - key as keyof typeof ENVIRONMENT_VARIABLES_MASKING_CONFIG - ]; - const options = - varMaskingConfig.strategy === - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS - ? { chars: varMaskingConfig.chars } - : undefined; - - value = environmentVariableMaskSensitiveData( - value, - varMaskingConfig.strategy, - { ...options, variableName: key }, - ); - } - - result[key] = { - value, - metadata: envMetadata, - }; - }); - - return result; - } -} diff --git a/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts index 75a2fadfd46..e4aff027097 100644 --- a/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/exception-handler.module-factory.ts @@ -1,22 +1,22 @@ import { HttpAdapterHost } from '@nestjs/core'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OPTIONS_TYPE } from 'src/engine/core-modules/exception-handler/exception-handler.module-definition'; import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; /** * ExceptionHandler Module factory * @returns ExceptionHandlerModuleOptions - * @param environmentService + * @param twentyConfigService * @param adapterHost */ export const exceptionHandlerModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, adapterHost: HttpAdapterHost, ): Promise => { - const driverType = environmentService.get('EXCEPTION_HANDLER_DRIVER'); + const driverType = twentyConfigService.get('EXCEPTION_HANDLER_DRIVER'); switch (driverType) { case ExceptionHandlerDriver.Console: { @@ -28,12 +28,12 @@ export const exceptionHandlerModuleFactory = async ( return { type: ExceptionHandlerDriver.Sentry, options: { - environment: environmentService.get('SENTRY_ENVIRONMENT'), - release: environmentService.get('SENTRY_RELEASE'), - dsn: environmentService.get('SENTRY_DSN') ?? '', + environment: twentyConfigService.get('SENTRY_ENVIRONMENT'), + release: twentyConfigService.get('SENTRY_RELEASE'), + dsn: twentyConfigService.get('SENTRY_DSN') ?? '', serverInstance: adapterHost.httpAdapter?.getInstance(), debug: - environmentService.get('NODE_ENV') === NodeEnvironment.development, + twentyConfigService.get('NODE_ENV') === NodeEnvironment.development, }, }; } diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts index 1683645c6ee..edb23a2f2dc 100644 --- a/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.module-factory.ts @@ -1,25 +1,25 @@ import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageModuleOptions, StorageDriverType, } from 'src/engine/core-modules/file-storage/interfaces'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { resolveAbsolutePath } from 'src/utils/resolve-absolute-path'; /** * FileStorage Module factory * @returns FileStorageModuleOptions - * @param environmentService + * @param twentyConfigService */ export const fileStorageModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): Promise => { - const driverType = environmentService.get('STORAGE_TYPE'); + const driverType = twentyConfigService.get('STORAGE_TYPE'); switch (driverType) { case StorageDriverType.Local: { - const storagePath = environmentService.get('STORAGE_LOCAL_PATH'); + const storagePath = twentyConfigService.get('STORAGE_LOCAL_PATH'); return { type: StorageDriverType.Local, @@ -29,11 +29,11 @@ export const fileStorageModuleFactory = async ( }; } case StorageDriverType.S3: { - const bucketName = environmentService.get('STORAGE_S3_NAME'); - const endpoint = environmentService.get('STORAGE_S3_ENDPOINT'); - const region = environmentService.get('STORAGE_S3_REGION'); - const accessKeyId = environmentService.get('STORAGE_S3_ACCESS_KEY_ID'); - const secretAccessKey = environmentService.get( + const bucketName = twentyConfigService.get('STORAGE_S3_NAME'); + const endpoint = twentyConfigService.get('STORAGE_S3_ENDPOINT'); + const region = twentyConfigService.get('STORAGE_S3_REGION'); + const accessKeyId = twentyConfigService.get('STORAGE_S3_ACCESS_KEY_ID'); + const secretAccessKey = twentyConfigService.get( 'STORAGE_S3_SECRET_ACCESS_KEY', ); diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts index d0de77e23c6..f2d10993145 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/file-upload.module.ts @@ -3,11 +3,11 @@ import { Module } from '@nestjs/common'; import { FileUploadResolver } from 'src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileModule } from 'src/engine/core-modules/file/file.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Module({ imports: [FileModule], - providers: [FileUploadService, FileUploadResolver, EnvironmentService], + providers: [FileUploadService, FileUploadResolver, TwentyConfigService], exports: [FileUploadService, FileUploadResolver], }) export class FileUploadModule {} diff --git a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts index 9633227b3c8..850cd9aff89 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { FileUploadResolver } from './file-upload.resolver'; @@ -17,7 +17,7 @@ describe('FileUploadResolver', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, ], diff --git a/packages/twenty-server/src/engine/core-modules/file/file.module.ts b/packages/twenty-server/src/engine/core-modules/file/file.module.ts index c52dc0f92ca..b8a3b356bf0 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FilePathGuard } from 'src/engine/core-modules/file/guards/file-path-guard'; import { FileDeletionJob } from 'src/engine/core-modules/file/jobs/file-deletion.job'; import { FileWorkspaceFolderDeletionJob } from 'src/engine/core-modules/file/jobs/file-workspace-folder-deletion.job'; import { FileAttachmentListener } from 'src/engine/core-modules/file/listeners/file-attachment.listener'; import { FileWorkspaceMemberListener } from 'src/engine/core-modules/file/listeners/file-workspace-member.listener'; import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { FileController } from './controllers/file.controller'; import { FileService } from './services/file.service'; @@ -15,7 +15,7 @@ import { FileService } from './services/file.service'; imports: [JwtModule], providers: [ FileService, - EnvironmentService, + TwentyConfigService, FilePathGuard, FileAttachmentListener, FileWorkspaceMemberListener, diff --git a/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts b/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts index ecc5ee5fa42..387b71e2a38 100644 --- a/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/services/file.service.spec.ts @@ -1,8 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; +import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { FileService } from './file.service'; @@ -18,7 +18,7 @@ describe('FileService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, { diff --git a/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts b/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts index e40f540dbfa..e7af3a44c68 100644 --- a/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts +++ b/packages/twenty-server/src/engine/core-modules/file/services/file.service.ts @@ -2,16 +2,16 @@ import { Injectable } from '@nestjs/common'; import { Stream } from 'stream'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class FileService { constructor( private readonly jwtWrapperService: JwtWrapperService, private readonly fileStorageService: FileStorageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} async getFileStream( @@ -28,7 +28,7 @@ export class FileService { } async encodeFileToken(payloadToEncode: Record) { - const fileTokenExpiresIn = this.environmentService.get( + const fileTokenExpiresIn = this.twentyConfigService.get( 'FILE_TOKEN_EXPIRES_IN', ); const secret = this.jwtWrapperService.generateAppSecret( diff --git a/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts b/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts index 73f857b05dd..30296cb2a61 100644 --- a/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts +++ b/packages/twenty-server/src/engine/core-modules/graphql/utils/generate-graphql-error-from-error.util.ts @@ -1,4 +1,4 @@ -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { BaseGraphQLError, diff --git a/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts b/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts index 26f9555b592..deda56193af 100644 --- a/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts +++ b/packages/twenty-server/src/engine/core-modules/guard-redirect/services/guard-redirect.service.ts @@ -2,17 +2,17 @@ import { ExecutionContext, Injectable } from '@nestjs/common'; import { Request } from 'express'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { CustomException } from 'src/utils/custom-exception'; import { AuthException } from 'src/engine/core-modules/auth/auth.exception'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; +import { CustomException } from 'src/utils/custom-exception'; @Injectable() export class GuardRedirectService { constructor( private readonly domainManagerService: DomainManagerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly exceptionHandlerService: ExceptionHandlerService, ) {} @@ -52,7 +52,7 @@ export class GuardRedirectService { customDomain: subdomainAndCustomDomainFromReferer.customDomain, } : { - subdomain: this.environmentService.get('DEFAULT_SUBDOMAIN'), + subdomain: this.twentyConfigService.get('DEFAULT_SUBDOMAIN'), customDomain: null, }; } diff --git a/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts b/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts index 8a689819cbd..6a7dd20c676 100644 --- a/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts +++ b/packages/twenty-server/src/engine/core-modules/jwt/jwt.module.ts @@ -2,24 +2,24 @@ import { Module } from '@nestjs/common'; import { JwtModule as NestJwtModule } from '@nestjs/jwt'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; const InternalJwtModule = NestJwtModule.registerAsync({ - useFactory: async (environmentService: EnvironmentService) => { + useFactory: async (twentyConfigService: TwentyConfigService) => { return { - secret: environmentService.get('APP_SECRET'), + secret: twentyConfigService.get('APP_SECRET'), signOptions: { - expiresIn: environmentService.get('ACCESS_TOKEN_EXPIRES_IN'), + expiresIn: twentyConfigService.get('ACCESS_TOKEN_EXPIRES_IN'), }, }; }, - inject: [EnvironmentService], + inject: [TwentyConfigService], }); @Module({ - imports: [InternalJwtModule, EnvironmentModule], + imports: [InternalJwtModule, TwentyConfigModule], controllers: [], providers: [JwtWrapperService], exports: [JwtWrapperService], diff --git a/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts b/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts index de94bfe878e..e5c803cde8d 100644 --- a/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts +++ b/packages/twenty-server/src/engine/core-modules/jwt/services/jwt-wrapper.service.ts @@ -12,7 +12,7 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type WorkspaceTokenType = | 'ACCESS' @@ -27,7 +27,7 @@ export type WorkspaceTokenType = export class JwtWrapperService { constructor( private readonly jwtService: JwtService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} sign(payload: string | object, options?: JwtSignOptions): string { @@ -102,7 +102,7 @@ export class JwtWrapperService { } generateAppSecret(type: WorkspaceTokenType, workspaceId?: string): string { - const appSecret = this.environmentService.get('APP_SECRET'); + const appSecret = this.twentyConfigService.get('APP_SECRET'); if (!appSecret) { throw new Error('APP_SECRET is not set'); @@ -114,7 +114,7 @@ export class JwtWrapperService { } generateAppSecretLegacy(): string { - const accessTokenSecret = this.environmentService.get( + const accessTokenSecret = this.twentyConfigService.get( 'ACCESS_TOKEN_SECRET', ); diff --git a/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts index e0ea03e54ba..ca52375ace6 100644 --- a/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-chat-model/llm-chat-model.module-factory.ts @@ -1,11 +1,11 @@ import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const llmChatModelModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ) => { - const driver = environmentService.get('LLM_CHAT_MODEL_DRIVER'); + const driver = twentyConfigService.get('LLM_CHAT_MODEL_DRIVER'); switch (driver) { case LLMChatModelDriver.OpenAI: { diff --git a/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts index 94abe251ebb..5f716415a84 100644 --- a/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/llm-tracing/llm-tracing.module-factory.ts @@ -1,19 +1,19 @@ import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const llmTracingModuleFactory = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ) => { - const driver = environmentService.get('LLM_TRACING_DRIVER'); + const driver = twentyConfigService.get('LLM_TRACING_DRIVER'); switch (driver) { case LLMTracingDriver.Console: { return { type: LLMTracingDriver.Console as const }; } case LLMTracingDriver.Langfuse: { - const secretKey = environmentService.get('LANGFUSE_SECRET_KEY'); - const publicKey = environmentService.get('LANGFUSE_PUBLIC_KEY'); + const secretKey = twentyConfigService.get('LANGFUSE_SECRET_KEY'); + const publicKey = twentyConfigService.get('LANGFUSE_PUBLIC_KEY'); if (!(secretKey && publicKey)) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts b/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts index 94b490fdc37..4992061585a 100644 --- a/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/logger/logger.module-factory.ts @@ -1,19 +1,19 @@ -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { - LoggerModuleOptions, LoggerDriverType, + LoggerModuleOptions, } from 'src/engine/core-modules/logger/interfaces'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; /** * Logger Module factory * @returns LoggerModuleOptions - * @param environmentService + * @param twentyConfigService */ export const loggerModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): Promise => { - const driverType = environmentService.get('LOGGER_DRIVER'); - const logLevels = environmentService.get('LOG_LEVELS'); + const driverType = twentyConfigService.get('LOGGER_DRIVER'); + const logLevels = twentyConfigService.get('LOG_LEVELS'); switch (driverType) { case LoggerDriverType.Console: { diff --git a/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts index 12fbff397f8..6255afa4090 100644 --- a/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/message-queue/message-queue.module-factory.ts @@ -1,18 +1,18 @@ -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { BullMQDriverFactoryOptions, MessageQueueDriverType, MessageQueueModuleOptions, } from 'src/engine/core-modules/message-queue/interfaces'; import { RedisClientService } from 'src/engine/core-modules/redis-client/redis-client.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; /** * MessageQueue Module factory * @returns MessageQueueModuleOptions - * @param environmentService + * @param twentyConfigService */ export const messageQueueModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, redisClientService: RedisClientService, ): Promise => { const driverType = MessageQueueDriverType.BullMQ; @@ -26,7 +26,7 @@ export const messageQueueModuleFactory = async ( } satisfies SyncDriverFactoryOptions; } case MessageQueueDriverType.PgBoss: { - const connectionString = environmentService.get('PG_DATABASE_URL'); + const connectionString = twentyConfigService.get('PG_DATABASE_URL'); return { type: MessageQueueDriverType.PgBoss, diff --git a/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts b/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts index 9666aef8de4..3fb84e1bf44 100644 --- a/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts +++ b/packages/twenty-server/src/engine/core-modules/metrics/metrics-cache.service.ts @@ -3,8 +3,8 @@ import { Injectable } from '@nestjs/common'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; const CACHE_BUCKET_DURATION_MS = 15000; // 15 seconds window for each cache bucket @@ -16,9 +16,9 @@ export class MetricsCacheService { constructor( @InjectCacheStorage(CacheStorageNamespace.EngineHealth) private readonly cacheStorage: CacheStorageService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) { - this.healthMetricsTimeWindowInMinutes = this.environmentService.get( + this.healthMetricsTimeWindowInMinutes = this.twentyConfigService.get( 'HEALTH_METRICS_TIME_WINDOW_IN_MINUTES', ); this.healthCacheTtl = this.healthMetricsTimeWindowInMinutes * 60000 * 2; diff --git a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts index 9ac93d60451..3da44988c8f 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.spec.ts @@ -1,8 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OpenApiService } from 'src/engine/core-modules/open-api/open-api.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; describe('OpenApiService', () => { @@ -21,7 +21,7 @@ describe('OpenApiService', () => { useValue: {}, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: {}, }, ], diff --git a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts index 980842cd785..5e92412fc50 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/open-api.service.ts @@ -6,7 +6,6 @@ import { capitalize } from 'twenty-shared/utils'; import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action'; import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { baseSchema } from 'src/engine/core-modules/open-api/utils/base-schema.utils'; import { computeMetadataSchemaComponents, @@ -36,6 +35,7 @@ import { getFindOneResponse200, getUpdateOneResponse200, } from 'src/engine/core-modules/open-api/utils/responses.utils'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { getServerUrl } from 'src/utils/get-server-url'; @@ -43,14 +43,14 @@ import { getServerUrl } from 'src/utils/get-server-url'; export class OpenApiService { constructor( private readonly accessTokenService: AccessTokenService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly objectMetadataService: ObjectMetadataService, ) {} async generateCoreSchema(request: Request): Promise { const baseUrl = getServerUrl( request, - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('SERVER_URL'), ); const schema = baseSchema('core', baseUrl); @@ -123,7 +123,7 @@ export class OpenApiService { ): Promise { const baseUrl = getServerUrl( request, - this.environmentService.get('SERVER_URL'), + this.twentyConfigService.get('SERVER_URL'), ); const schema = baseSchema('metadata', baseUrl); diff --git a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts index 8e62a0db736..312c290e2ee 100644 --- a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts +++ b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.module.ts @@ -1,11 +1,11 @@ import { Global, Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { RedisClientService } from 'src/engine/core-modules/redis-client/redis-client.service'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; @Global() @Module({ - imports: [EnvironmentModule], + imports: [TwentyConfigModule], providers: [RedisClientService], exports: [RedisClientService], }) diff --git a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts index 57297323e85..25b9de27ae9 100644 --- a/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts +++ b/packages/twenty-server/src/engine/core-modules/redis-client/redis-client.service.ts @@ -2,17 +2,17 @@ import { Injectable, OnModuleDestroy } from '@nestjs/common'; import IORedis from 'ioredis'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class RedisClientService implements OnModuleDestroy { private redisClient: IORedis | null = null; - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} getClient() { if (!this.redisClient) { - const redisUrl = this.environmentService.get('REDIS_URL'); + const redisUrl = this.twentyConfigService.get('REDIS_URL'); if (!redisUrl) { throw new Error('REDIS_URL must be defined'); diff --git a/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts b/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts index 6f6f23da9ac..93e4d80ff48 100644 --- a/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts +++ b/packages/twenty-server/src/engine/core-modules/serverless/serverless-module.factory.ts @@ -1,17 +1,17 @@ import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { ServerlessDriverType, ServerlessModuleOptions, } from 'src/engine/core-modules/serverless/serverless.interface'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const serverlessModuleFactory = async ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, fileStorageService: FileStorageService, ): Promise => { - const driverType = environmentService.get('SERVERLESS_TYPE'); + const driverType = twentyConfigService.get('SERVERLESS_TYPE'); const options = { fileStorageService }; switch (driverType) { @@ -22,16 +22,16 @@ export const serverlessModuleFactory = async ( }; } case ServerlessDriverType.Lambda: { - const region = environmentService.get('SERVERLESS_LAMBDA_REGION'); - const accessKeyId = environmentService.get( + const region = twentyConfigService.get('SERVERLESS_LAMBDA_REGION'); + const accessKeyId = twentyConfigService.get( 'SERVERLESS_LAMBDA_ACCESS_KEY_ID', ); - const secretAccessKey = environmentService.get( + const secretAccessKey = twentyConfigService.get( 'SERVERLESS_LAMBDA_SECRET_ACCESS_KEY', ); - const lambdaRole = environmentService.get('SERVERLESS_LAMBDA_ROLE'); + const lambdaRole = twentyConfigService.get('SERVERLESS_LAMBDA_ROLE'); - const subhostingRole = environmentService.get( + const subhostingRole = twentyConfigService.get( 'SERVERLESS_LAMBDA_SUBHOSTING_ROLE', ); diff --git a/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts b/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts index 84f7bed9035..9ec012f041e 100644 --- a/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts +++ b/packages/twenty-server/src/engine/core-modules/session-storage/session-storage.module-factory.ts @@ -5,16 +5,16 @@ import session from 'express-session'; import { createClient } from 'redis'; import { CacheStorageType } from 'src/engine/core-modules/cache-storage/types/cache-storage-type.enum'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export const getSessionStorageOptions = ( - environmentService: EnvironmentService, + twentyConfigService: TwentyConfigService, ): session.SessionOptions => { const cacheStorageType = CacheStorageType.Redis; - const SERVER_URL = environmentService.get('SERVER_URL'); + const SERVER_URL = twentyConfigService.get('SERVER_URL'); - const appSecret = environmentService.get('APP_SECRET'); + const appSecret = twentyConfigService.get('APP_SECRET'); if (!appSecret) { throw new Error('APP_SECRET is not set'); @@ -44,7 +44,7 @@ export const getSessionStorageOptions = ( return sessionStorage; }*/ case CacheStorageType.Redis: { - const connectionString = environmentService.get('REDIS_URL'); + const connectionString = twentyConfigService.get('REDIS_URL'); if (!connectionString) { throw new Error( diff --git a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts index 37a04d4f439..728639de401 100644 --- a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.spec.ts @@ -3,12 +3,12 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { SSOService } from 'src/engine/core-modules/sso/services/sso.service'; import { BillingService } from 'src/engine/core-modules/billing/services/billing.service'; -import { WorkspaceSSOIdentityProvider } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { SSOService } from 'src/engine/core-modules/sso/services/sso.service'; import { SSOException } from 'src/engine/core-modules/sso/sso.exception'; +import { WorkspaceSSOIdentityProvider } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; describe('SSOService', () => { let service: SSOService; @@ -30,7 +30,7 @@ describe('SSOService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, diff --git a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts index adb9c496879..5d38b00fd45 100644 --- a/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts +++ b/packages/twenty-server/src/engine/core-modules/sso/services/sso.service.ts @@ -8,7 +8,7 @@ import { Repository } from 'typeorm'; import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum'; import { BillingService } from 'src/engine/core-modules/billing/services/billing.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { SSOException, SSOExceptionCode, @@ -23,7 +23,7 @@ import { OIDCResponseType, WorkspaceSSOIdentityProvider, } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity'; -import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class SSOService { @@ -31,7 +31,7 @@ export class SSOService { constructor( @InjectRepository(WorkspaceSSOIdentityProvider, 'core') private readonly workspaceSSOIdentityProviderRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly billingService: BillingService, private readonly exceptionHandlerService: ExceptionHandlerService, ) {} @@ -139,7 +139,7 @@ export class SSOService { buildCallbackUrl( identityProvider: Pick, ) { - const callbackURL = new URL(this.environmentService.get('SERVER_URL')); + const callbackURL = new URL(this.twentyConfigService.get('SERVER_URL')); callbackURL.pathname = `/auth/${identityProvider.type.toLowerCase()}/callback`; @@ -154,7 +154,9 @@ export class SSOService { identityProvider: Pick, searchParams?: Record, ) { - const authorizationUrl = new URL(this.environmentService.get('SERVER_URL')); + const authorizationUrl = new URL( + this.twentyConfigService.get('SERVER_URL'), + ); authorizationUrl.pathname = `/auth/${identityProvider.type.toLowerCase()}/login/${identityProvider.id}`; diff --git a/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts index 6f59f984781..acf3e77bc28 100644 --- a/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts +++ b/packages/twenty-server/src/engine/core-modules/telemetry/telemetry.service.ts @@ -1,7 +1,7 @@ import { HttpService } from '@nestjs/axios'; import { Injectable, Logger } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; type CreateEventInput = { action: string; @@ -13,7 +13,7 @@ export class TelemetryService { private readonly logger = new Logger(TelemetryService.name); constructor( - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly httpService: HttpService, ) {} @@ -22,7 +22,7 @@ export class TelemetryService { userId: string | null | undefined, workspaceId: string | null | undefined, ) { - if (!this.environmentService.get('TELEMETRY_ENABLED')) { + if (!this.twentyConfigService.get('TELEMETRY_ENABLED')) { return { success: true }; } diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts similarity index 63% rename from packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts index 2cac00268a2..ad9fd467edb 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts @@ -16,33 +16,33 @@ import { import { isDefined } from 'twenty-shared/utils'; import { EmailDriver } from 'src/engine/core-modules/email/interfaces/email.interface'; -import { AwsRegion } from 'src/engine/core-modules/environment/interfaces/aws-region.interface'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; -import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface'; import { LLMChatModelDriver } from 'src/engine/core-modules/llm-chat-model/interfaces/llm-chat-model.interface'; import { LLMTracingDriver } from 'src/engine/core-modules/llm-tracing/interfaces/llm-tracing.interface'; +import { AwsRegion } from 'src/engine/core-modules/twenty-config/interfaces/aws-region.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; +import { SupportDriver } from 'src/engine/core-modules/twenty-config/interfaces/support.interface'; import { CaptchaDriverType } from 'src/engine/core-modules/captcha/interfaces'; -import { CastToBoolean } from 'src/engine/core-modules/environment/decorators/cast-to-boolean.decorator'; -import { CastToLogLevelArray } from 'src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator'; -import { CastToMeterDriverArray } from 'src/engine/core-modules/environment/decorators/cast-to-meter-driver.decorator'; -import { CastToPositiveNumber } from 'src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator'; -import { EnvironmentVariablesMetadata } from 'src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator'; -import { IsAWSRegion } from 'src/engine/core-modules/environment/decorators/is-aws-region.decorator'; -import { IsDuration } from 'src/engine/core-modules/environment/decorators/is-duration.decorator'; -import { IsOptionalOrEmptyString } from 'src/engine/core-modules/environment/decorators/is-optional-or-empty-string.decorator'; -import { IsStrictlyLowerThan } from 'src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator'; -import { IsTwentySemVer } from 'src/engine/core-modules/environment/decorators/is-twenty-semver.decorator'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; import { StorageDriverType } from 'src/engine/core-modules/file-storage/interfaces'; import { LoggerDriverType } from 'src/engine/core-modules/logger/interfaces'; import { MeterDriver } from 'src/engine/core-modules/metrics/types/meter-driver.type'; import { ServerlessDriverType } from 'src/engine/core-modules/serverless/serverless.interface'; +import { CastToBoolean } from 'src/engine/core-modules/twenty-config/decorators/cast-to-boolean.decorator'; +import { CastToLogLevelArray } from 'src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator'; +import { CastToMeterDriverArray } from 'src/engine/core-modules/twenty-config/decorators/cast-to-meter-driver.decorator'; +import { CastToPositiveNumber } from 'src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator'; +import { ConfigVariablesMetadata } from 'src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator'; +import { IsAWSRegion } from 'src/engine/core-modules/twenty-config/decorators/is-aws-region.decorator'; +import { IsDuration } from 'src/engine/core-modules/twenty-config/decorators/is-duration.decorator'; +import { IsOptionalOrEmptyString } from 'src/engine/core-modules/twenty-config/decorators/is-optional-or-empty-string.decorator'; +import { IsStrictlyLowerThan } from 'src/engine/core-modules/twenty-config/decorators/is-strictly-lower-than.decorator'; +import { IsTwentySemVer } from 'src/engine/core-modules/twenty-config/decorators/is-twenty-semver.decorator'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; -export class EnvironmentVariables { - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, +export class ConfigVariables { + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Enable or disable password authentication for users', }) @CastToBoolean() @@ -50,8 +50,8 @@ export class EnvironmentVariables { @IsBoolean() AUTH_PASSWORD_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Prefills tim@apple.dev in the login form, used in local development for quicker sign-in', }) @@ -61,8 +61,8 @@ export class EnvironmentVariables { @ValidateIf((env) => env.AUTH_PASSWORD_ENABLED) SIGN_IN_PREFILLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Require email verification for user accounts', }) @CastToBoolean() @@ -70,37 +70,37 @@ export class EnvironmentVariables { @IsBoolean() IS_EMAIL_VERIFICATION_REQUIRED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the email verification token is valid', }) @IsDuration() @IsOptional() EMAIL_VERIFICATION_TOKEN_EXPIRES_IN = '1h'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the password reset token is valid', }) @IsDuration() @IsOptional() PASSWORD_RESET_TOKEN_EXPIRES_IN = '5m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Enable or disable the Google Calendar integration', }) @CastToBoolean() CALENDAR_PROVIDER_GOOGLE_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Callback URL for Google Auth APIs', }) AUTH_GOOGLE_APIS_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Enable or disable Google Single Sign-On (SSO)', }) @CastToBoolean() @@ -108,42 +108,42 @@ export class EnvironmentVariables { @IsBoolean() AUTH_GOOGLE_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, + isSensitive: true, description: 'Client ID for Google authentication', }) @IsString() @ValidateIf((env) => env.AUTH_GOOGLE_ENABLED) AUTH_GOOGLE_CLIENT_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, + isSensitive: true, description: 'Client secret for Google authentication', }) @IsString() @ValidateIf((env) => env.AUTH_GOOGLE_ENABLED) AUTH_GOOGLE_CLIENT_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, + isSensitive: true, description: 'Callback URL for Google authentication', }) @IsUrl({ require_tld: false, require_protocol: true }) @ValidateIf((env) => env.AUTH_GOOGLE_ENABLED) AUTH_GOOGLE_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.GoogleAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.GoogleAuth, description: 'Enable or disable the Gmail messaging integration', }) @CastToBoolean() MESSAGING_PROVIDER_GMAIL_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, description: 'Enable or disable Microsoft authentication', }) @CastToBoolean() @@ -151,59 +151,59 @@ export class EnvironmentVariables { @IsBoolean() AUTH_MICROSOFT_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Client ID for Microsoft authentication', }) @IsString() @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_CLIENT_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Client secret for Microsoft authentication', }) @IsString() @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_CLIENT_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Callback URL for Microsoft authentication', }) @IsUrl({ require_tld: false, require_protocol: true }) @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, + isSensitive: true, description: 'Callback URL for Microsoft APIs', }) @IsUrl({ require_tld: false, require_protocol: true }) @ValidateIf((env) => env.AUTH_MICROSOFT_ENABLED) AUTH_MICROSOFT_APIS_CALLBACK_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, description: 'Enable or disable the Microsoft messaging integration', }) @CastToBoolean() MESSAGING_PROVIDER_MICROSOFT_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.MicrosoftAuth, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.MicrosoftAuth, description: 'Enable or disable the Microsoft Calendar integration', }) @CastToBoolean() CALENDAR_PROVIDER_MICROSOFT_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, + isSensitive: true, description: 'Legacy variable to be deprecated when all API Keys expire. Replaced by APP_KEY', }) @@ -211,91 +211,91 @@ export class EnvironmentVariables { @IsString() ACCESS_TOKEN_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the access token is valid', }) @IsDuration() @IsOptional() ACCESS_TOKEN_EXPIRES_IN = '30m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the refresh token is valid', }) @IsOptional() REFRESH_TOKEN_EXPIRES_IN = '60d'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Cooldown period for refreshing tokens', }) @IsDuration() @IsOptional() REFRESH_TOKEN_COOL_DOWN = '1m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the login token is valid', }) @IsDuration() @IsOptional() LOGIN_TOKEN_EXPIRES_IN = '15m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the file token is valid', }) @IsDuration() @IsOptional() FILE_TOKEN_EXPIRES_IN = '1d'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the invitation token is valid', }) @IsDuration() @IsOptional() INVITATION_TOKEN_EXPIRES_IN = '30d'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Duration for which the short-term token is valid', }) SHORT_TERM_TOKEN_EXPIRES_IN = '5m'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Email address used as the sender for outgoing emails', }) EMAIL_FROM_ADDRESS = 'noreply@yourdomain.com'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Email address used for system notifications', }) EMAIL_SYSTEM_ADDRESS = 'system@yourdomain.com'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Name used in the From header for outgoing emails', }) EMAIL_FROM_NAME = 'Felix from Twenty'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Email driver to use for sending emails', }) EMAIL_DRIVER: EmailDriver = EmailDriver.Logger; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'SMTP host for sending emails', }) EMAIL_SMTP_HOST: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'Use unsecure connection for SMTP', }) @CastToBoolean() @@ -303,60 +303,60 @@ export class EnvironmentVariables { @IsBoolean() EMAIL_SMTP_NO_TLS = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'SMTP port for sending emails', }) @CastToPositiveNumber() EMAIL_SMTP_PORT = 587; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, description: 'SMTP user for authentication', }) EMAIL_SMTP_USER: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.EmailSettings, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.EmailSettings, + isSensitive: true, description: 'SMTP password for authentication', }) EMAIL_SMTP_PASSWORD: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'Type of storage to use (local or S3)', }) @IsEnum(StorageDriverType) @IsOptional() STORAGE_TYPE: StorageDriverType = StorageDriverType.Local; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'Local path for storage when using local storage type', }) @IsString() @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.Local) STORAGE_LOCAL_PATH = '.local-storage'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'S3 region for storage when using S3 storage type', }) @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.S3) @IsAWSRegion() STORAGE_S3_REGION: AwsRegion; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'S3 bucket name for storage when using S3 storage type', }) @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.S3) @IsString() STORAGE_S3_NAME: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, description: 'S3 endpoint for storage when using S3 storage type', }) @ValidateIf((env) => env.STORAGE_TYPE === StorageDriverType.S3) @@ -364,9 +364,9 @@ export class EnvironmentVariables { @IsOptional() STORAGE_S3_ENDPOINT: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, + isSensitive: true, description: 'S3 access key ID for authentication when using S3 storage type', }) @@ -375,9 +375,9 @@ export class EnvironmentVariables { @IsOptional() STORAGE_S3_ACCESS_KEY_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.StorageConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.StorageConfig, + isSensitive: true, description: 'S3 secret access key for authentication when using S3 storage type', }) @@ -386,47 +386,47 @@ export class EnvironmentVariables { @IsOptional() STORAGE_S3_SECRET_ACCESS_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Type of serverless execution (local or Lambda)', }) @IsEnum(ServerlessDriverType) @IsOptional() SERVERLESS_TYPE: ServerlessDriverType = ServerlessDriverType.Local; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Throttle limit for serverless function execution', }) @CastToPositiveNumber() SERVERLESS_FUNCTION_EXEC_THROTTLE_LIMIT = 10; // milliseconds - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Time-to-live for serverless function execution throttle', }) @CastToPositiveNumber() SERVERLESS_FUNCTION_EXEC_THROTTLE_TTL = 1000; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Region for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @IsAWSRegion() SERVERLESS_LAMBDA_REGION: AwsRegion; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'IAM role for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @IsString() SERVERLESS_LAMBDA_ROLE: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, description: 'Role to assume when hosting lambdas in dedicated AWS account', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @@ -434,9 +434,9 @@ export class EnvironmentVariables { @IsOptional() SERVERLESS_LAMBDA_SUBHOSTING_ROLE?: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, + isSensitive: true, description: 'Access key ID for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @@ -444,9 +444,9 @@ export class EnvironmentVariables { @IsOptional() SERVERLESS_LAMBDA_ACCESS_KEY_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerlessConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerlessConfig, + isSensitive: true, description: 'Secret access key for AWS Lambda functions', }) @ValidateIf((env) => env.SERVERLESS_TYPE === ServerlessDriverType.Lambda) @@ -454,8 +454,8 @@ export class EnvironmentVariables { @IsOptional() SERVERLESS_LAMBDA_SECRET_ACCESS_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.AnalyticsConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.AnalyticsConfig, description: 'Enable or disable analytics for telemetry', }) @CastToBoolean() @@ -463,8 +463,8 @@ export class EnvironmentVariables { @IsBoolean() ANALYTICS_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Enable or disable telemetry logging', }) @CastToBoolean() @@ -472,8 +472,8 @@ export class EnvironmentVariables { @IsBoolean() TELEMETRY_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Enable or disable billing features', }) @CastToBoolean() @@ -481,16 +481,16 @@ export class EnvironmentVariables { @IsBoolean() IS_BILLING_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Link required for billing plan', }) @IsString() @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_PLAN_REQUIRED_LINK: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Duration of free trial with credit card in days', }) @IsNumber() @@ -499,8 +499,8 @@ export class EnvironmentVariables { @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_FREE_TRIAL_WITH_CREDIT_CARD_DURATION_IN_DAYS = 30; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, description: 'Duration of free trial without credit card in days', }) @IsNumber() @@ -509,34 +509,34 @@ export class EnvironmentVariables { @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_FREE_TRIAL_WITHOUT_CREDIT_CARD_DURATION_IN_DAYS = 7; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, + isSensitive: true, description: 'Stripe API key for billing', }) @IsString() @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_STRIPE_API_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.BillingConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.BillingConfig, + isSensitive: true, description: 'Stripe webhook secret for billing', }) @IsString() @ValidateIf((env) => env.IS_BILLING_ENABLED === true) BILLING_STRIPE_WEBHOOK_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Url for the frontend application', }) @IsUrl({ require_tld: false, require_protocol: true }) @IsOptional() FRONTEND_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Default subdomain for the frontend when multi-workspace is enabled', }) @@ -544,16 +544,16 @@ export class EnvironmentVariables { @ValidateIf((env) => env.IS_MULTIWORKSPACE_ENABLED) DEFAULT_SUBDOMAIN = 'app'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'ID for the Chrome extension', }) @IsString() @IsOptional() CHROME_EXTENSION_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Enable or disable buffering for logs before sending', }) @CastToBoolean() @@ -561,8 +561,8 @@ export class EnvironmentVariables { @IsOptional() LOGGER_IS_BUFFER_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Driver used for handling exceptions (Console or Sentry)', }) @IsEnum(ExceptionHandlerDriver) @@ -570,39 +570,39 @@ export class EnvironmentVariables { EXCEPTION_HANDLER_DRIVER: ExceptionHandlerDriver = ExceptionHandlerDriver.Console; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Logging, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Logging, description: 'Levels of logging to be captured', }) @CastToLogLevelArray() @IsOptional() LOG_LEVELS: LogLevel[] = ['log', 'error', 'warn']; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Metering, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Metering, description: 'Driver used for collect metrics (OpenTelemetry or Console)', }) @CastToMeterDriverArray() @IsOptional() METER_DRIVER: MeterDriver[] = []; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Metering, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Metering, description: 'Endpoint URL for the OpenTelemetry collector', }) @IsOptional() OTLP_COLLECTOR_ENDPOINT_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Driver used for logging (only console for now)', }) @IsEnum(LoggerDriverType) @IsOptional() LOGGER_DRIVER: LoggerDriverType = LoggerDriverType.Console; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Data Source Name (DSN) for Sentry logging', }) @ValidateIf( @@ -611,8 +611,8 @@ export class EnvironmentVariables { @IsString() SENTRY_DSN: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Front-end DSN for Sentry logging', }) @ValidateIf( @@ -621,8 +621,8 @@ export class EnvironmentVariables { @IsString() SENTRY_FRONT_DSN: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Release version for Sentry logging', }) @ValidateIf( @@ -632,8 +632,8 @@ export class EnvironmentVariables { @IsOptional() SENTRY_RELEASE: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ExceptionHandler, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ExceptionHandler, description: 'Environment name for Sentry logging', }) @ValidateIf( @@ -643,35 +643,35 @@ export class EnvironmentVariables { @IsOptional() SENTRY_ENVIRONMENT: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SupportChatConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SupportChatConfig, description: 'Driver used for support chat integration', }) @IsEnum(SupportDriver) @IsOptional() SUPPORT_DRIVER: SupportDriver = SupportDriver.None; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SupportChatConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SupportChatConfig, + isSensitive: true, description: 'Chat ID for the support front integration', }) @ValidateIf((env) => env.SUPPORT_DRIVER === SupportDriver.Front) @IsString() SUPPORT_FRONT_CHAT_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SupportChatConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SupportChatConfig, + isSensitive: true, description: 'HMAC key for the support front integration', }) @ValidateIf((env) => env.SUPPORT_DRIVER === SupportDriver.Front) @IsString() SUPPORT_FRONT_HMAC_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'Database connection URL', }) @IsDefined() @@ -683,8 +683,8 @@ export class EnvironmentVariables { }) PG_DATABASE_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Allow connections to a database with self-signed certificates', }) @@ -693,16 +693,16 @@ export class EnvironmentVariables { @IsOptional() PG_SSL_ALLOW_SELF_SIGNED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.TokensDuration, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.TokensDuration, description: 'Time-to-live for cache storage in seconds', }) @CastToPositiveNumber() CACHE_STORAGE_TTL: number = 3600 * 24 * 7; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'URL for cache storage (e.g., Redis connection URL)', }) @IsOptional() @@ -713,16 +713,16 @@ export class EnvironmentVariables { }) REDIS_URL: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Node environment (development, production, etc.)', }) @IsEnum(NodeEnvironment) @IsString() NODE_ENV: NodeEnvironment = NodeEnvironment.production; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Port for the node server', }) @CastToPositiveNumber() @@ -730,24 +730,24 @@ export class EnvironmentVariables { @IsOptional() NODE_PORT = 3000; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Base URL for the server', }) @IsUrl({ require_tld: false, require_protocol: true }) @IsOptional() SERVER_URL = 'http://localhost:3000'; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'Secret key for the application', }) @IsString() APP_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Maximum number of records affected by mutations', }) @CastToPositiveNumber() @@ -755,31 +755,31 @@ export class EnvironmentVariables { @IsNumber() MUTATION_MAXIMUM_AFFECTED_RECORDS = 100; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Time-to-live for API rate limiting in milliseconds', }) @CastToPositiveNumber() API_RATE_LIMITING_TTL = 100; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Maximum number of requests allowed in the rate limiting window', }) @CastToPositiveNumber() API_RATE_LIMITING_LIMIT = 500; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SSL, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SSL, description: 'Path to the SSL key for enabling HTTPS in local development', }) @IsString() @IsOptional() SSL_KEY_PATH: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.SSL, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.SSL, description: 'Path to the SSL certificate for enabling HTTPS in local development', }) @@ -787,65 +787,65 @@ export class EnvironmentVariables { @IsOptional() SSL_CERT_PATH: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CloudflareConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CloudflareConfig, + isSensitive: true, description: 'API key for Cloudflare integration', }) @IsString() @ValidateIf((env) => env.CLOUDFLARE_ZONE_ID) CLOUDFLARE_API_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CloudflareConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CloudflareConfig, description: 'Zone ID for Cloudflare integration', }) @IsString() @ValidateIf((env) => env.CLOUDFLARE_API_KEY) CLOUDFLARE_ZONE_ID: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Random string to validate queries from Cloudflare', }) @IsString() @IsOptional() CLOUDFLARE_WEBHOOK_SECRET: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, description: 'Driver for the LLM chat model', }) LLM_CHAT_MODEL_DRIVER: LLMChatModelDriver; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, + isSensitive: true, description: 'API key for OpenAI integration', }) OPENAI_API_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, + isSensitive: true, description: 'Secret key for Langfuse integration', }) LANGFUSE_SECRET_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, description: 'Public key for Langfuse integration', }) LANGFUSE_PUBLIC_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.LLM, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.LLM, description: 'Driver for LLM tracing', }) LLM_TRACING_DRIVER: LLMTracingDriver = LLMTracingDriver.Console; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Enable or disable multi-workspace support', }) @CastToBoolean() @@ -853,8 +853,8 @@ export class EnvironmentVariables { @IsBoolean() IS_MULTIWORKSPACE_ENABLED = false; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Number of inactive days before sending a deletion warning for workspaces. Used in the workspace deletion cron job to determine when to send warning emails.', }) @@ -866,8 +866,8 @@ export class EnvironmentVariables { }) WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION = 7; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Number of inactive days before soft deleting workspaces', }) @CastToPositiveNumber() @@ -878,16 +878,16 @@ export class EnvironmentVariables { }) WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION = 14; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Number of inactive days before deleting workspaces', }) @CastToPositiveNumber() @IsNumber() WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION = 21; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Maximum number of workspaces that can be deleted in a single execution', }) @@ -896,57 +896,57 @@ export class EnvironmentVariables { @ValidateIf((env) => env.MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION > 0) MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION = 5; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Throttle limit for workflow execution', }) @CastToPositiveNumber() WORKFLOW_EXEC_THROTTLE_LIMIT = 500; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.RateLimiting, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.RateLimiting, description: 'Time-to-live for workflow execution throttle in milliseconds', }) @CastToPositiveNumber() WORKFLOW_EXEC_THROTTLE_TTL = 1000; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CaptchaConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CaptchaConfig, description: 'Driver for captcha integration', }) @IsEnum(CaptchaDriverType) @IsOptional() CAPTCHA_DRIVER?: CaptchaDriverType; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CaptchaConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CaptchaConfig, + isSensitive: true, description: 'Site key for captcha integration', }) @IsString() @IsOptional() CAPTCHA_SITE_KEY?: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.CaptchaConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.CaptchaConfig, + isSensitive: true, description: 'Secret key for captcha integration', }) @IsString() @IsOptional() CAPTCHA_SECRET_KEY?: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, - sensitive: true, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, + isSensitive: true, description: 'License key for the Enterprise version', }) @IsString() @IsOptional() ENTERPRISE_KEY: string; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Health monitoring time window in minutes', }) @IsNumber() @@ -954,8 +954,8 @@ export class EnvironmentVariables { @IsOptional() HEALTH_METRICS_TIME_WINDOW_IN_MINUTES = 5; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.Other, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.Other, description: 'Enable or disable the attachment preview feature', }) @CastToBoolean() @@ -963,8 +963,8 @@ export class EnvironmentVariables { @IsBoolean() IS_ATTACHMENT_PREVIEW_ENABLED = true; - @EnvironmentVariablesMetadata({ - group: EnvironmentVariablesGroup.ServerConfig, + @ConfigVariablesMetadata({ + group: ConfigVariablesGroup.ServerConfig, description: 'Twenty server version', }) @IsOptionalOrEmptyString() @@ -972,10 +972,8 @@ export class EnvironmentVariables { APP_VERSION?: string; } -export const validate = ( - config: Record, -): EnvironmentVariables => { - const validatedConfig = plainToClass(EnvironmentVariables, config); +export const validate = (config: Record): ConfigVariables => { + const validatedConfig = plainToClass(ConfigVariables, config); const validationErrors = validateSync(validatedConfig, { strictGroups: true, @@ -1001,7 +999,7 @@ export const validate = ( if (validationErrors.length > 0) { logValidatonErrors(validationErrors, 'error'); - throw new Error('Environment variables validation failed'); + throw new Error('Config variables validation failed'); } return validatedConfig; diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts new file mode 100644 index 00000000000..fc4eae8b500 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/__tests__/config-variables-group-metadata.spec.ts @@ -0,0 +1,28 @@ +import { CONFIG_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/twenty-config/constants/config-variables-group-metadata'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; + +describe('CONFIG_VARIABLES_GROUP_METADATA', () => { + it('should include all ConfigVariablesGroup enum values', () => { + const enumValues = Object.values(ConfigVariablesGroup); + const metadataKeys = Object.keys(CONFIG_VARIABLES_GROUP_METADATA); + + enumValues.forEach((enumValue) => { + expect(metadataKeys).toContain(enumValue); + }); + + metadataKeys.forEach((key) => { + expect(enumValues).toContain(key); + }); + + expect(enumValues.length).toBe(metadataKeys.length); + }); + + it('should have unique position values', () => { + const positions = Object.values(CONFIG_VARIABLES_GROUP_METADATA).map( + (metadata) => metadata.position, + ); + const uniquePositions = new Set(positions); + + expect(positions.length).toBe(uniquePositions.size); + }); +}); diff --git a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-group-metadata.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-group-metadata.ts similarity index 77% rename from packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-group-metadata.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-group-metadata.ts index bc60b255313..ed5525c94f4 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/constants/environment-variables-group-metadata.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-group-metadata.ts @@ -1,4 +1,4 @@ -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; type GroupMetadata = { position: number; @@ -6,114 +6,114 @@ type GroupMetadata = { isHiddenOnLoad: boolean; }; -export const ENVIRONMENT_VARIABLES_GROUP_METADATA: Record< - EnvironmentVariablesGroup, +export const CONFIG_VARIABLES_GROUP_METADATA: Record< + ConfigVariablesGroup, GroupMetadata > = { - [EnvironmentVariablesGroup.ServerConfig]: { + [ConfigVariablesGroup.ServerConfig]: { position: 100, description: '', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.RateLimiting]: { + [ConfigVariablesGroup.RateLimiting]: { position: 200, description: 'We use this to limit the number of requests to the server. This is useful to prevent abuse.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.StorageConfig]: { + [ConfigVariablesGroup.StorageConfig]: { position: 300, description: 'By default, file uploads are stored on the local filesystem, which is suitable for traditional servers. However, for ephemeral deployment servers, it is essential to configure the variables here to set up an S3-compatible file system. This ensures that files remain unaffected by server redeploys.', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.GoogleAuth]: { + [ConfigVariablesGroup.GoogleAuth]: { position: 400, description: 'Configure Google integration (login, calendar, email)', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.MicrosoftAuth]: { + [ConfigVariablesGroup.MicrosoftAuth]: { position: 500, description: 'Configure Microsoft integration (login, calendar, email)', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.EmailSettings]: { + [ConfigVariablesGroup.EmailSettings]: { position: 600, description: 'This is used for emails that are sent by the app such as invitations to join a workspace. This is not used to email CRM contacts.', isHiddenOnLoad: false, }, - [EnvironmentVariablesGroup.Logging]: { + [ConfigVariablesGroup.Logging]: { position: 700, description: '', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.ExceptionHandler]: { + [ConfigVariablesGroup.ExceptionHandler]: { position: 800, description: 'By default, exceptions are sent to the logs. This should be enough for most self-hosting use-cases. For our cloud app we use Sentry.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.Metering]: { + [ConfigVariablesGroup.Metering]: { position: 900, description: 'By default, metrics are sent to the console. OpenTelemetry collector can be set up for self-hosting use-cases.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.Other]: { + [ConfigVariablesGroup.Other]: { position: 1000, description: "The variables in this section are mostly used for internal purposes (running our Cloud offering), but shouldn't usually be required for a simple self-hosted instance", isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.BillingConfig]: { + [ConfigVariablesGroup.BillingConfig]: { position: 1100, description: 'We use Stripe in our Cloud app to charge customers. Not relevant to Self-hosters.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.CaptchaConfig]: { + [ConfigVariablesGroup.CaptchaConfig]: { position: 1200, description: 'This protects critical endpoints like login and signup with a captcha to prevent bot attacks. Likely unnecessary for self-hosting scenarios.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.CloudflareConfig]: { + [ConfigVariablesGroup.CloudflareConfig]: { position: 1300, description: '', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.LLM]: { + [ConfigVariablesGroup.LLM]: { position: 1400, description: 'Configure the LLM provider and model to use for the app. This is experimental and not linked to any public feature.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.ServerlessConfig]: { + [ConfigVariablesGroup.ServerlessConfig]: { position: 1500, description: 'In our multi-tenant cloud app, we offload untrusted custom code from workflows to a serverless system (Lambda) for enhanced security and scalability. Self-hosters with a single tenant can typically ignore this configuration.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.SSL]: { + [ConfigVariablesGroup.SSL]: { position: 1600, description: 'Configure this if you want to setup SSL on your server or full end-to-end encryption. If you just want basic HTTPS, a simple setup like Cloudflare in flexible mode might be easier.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.SupportChatConfig]: { + [ConfigVariablesGroup.SupportChatConfig]: { position: 1700, description: 'We use this to setup a small support chat on the bottom left. Currently powered by Front.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.AnalyticsConfig]: { + [ConfigVariablesGroup.AnalyticsConfig]: { position: 1800, description: 'We’re running a test to perform analytics within the app. This will evolve.', isHiddenOnLoad: true, }, - [EnvironmentVariablesGroup.TokensDuration]: { + [ConfigVariablesGroup.TokensDuration]: { position: 1900, description: 'These have been set to sensible default so you probably don’t need to change them unless you have a specific use-case.', diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts new file mode 100644 index 00000000000..8be50ecca3a --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-masking-config.ts @@ -0,0 +1,29 @@ +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; + +type LastNCharsConfig = { + strategy: ConfigVariablesMaskingStrategies.LAST_N_CHARS; + chars: number; +}; + +type HidePasswordConfig = { + strategy: ConfigVariablesMaskingStrategies.HIDE_PASSWORD; +}; + +type MaskingConfigType = { + APP_SECRET: LastNCharsConfig; + PG_DATABASE_URL: HidePasswordConfig; + REDIS_URL: HidePasswordConfig; +}; + +export const CONFIG_VARIABLES_MASKING_CONFIG: MaskingConfigType = { + APP_SECRET: { + strategy: ConfigVariablesMaskingStrategies.LAST_N_CHARS, + chars: 5, + }, + PG_DATABASE_URL: { + strategy: ConfigVariablesMaskingStrategies.HIDE_PASSWORD, + }, + REDIS_URL: { + strategy: ConfigVariablesMaskingStrategies.HIDE_PASSWORD, + }, +} as const; diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts new file mode 100644 index 00000000000..921f6f786dc --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-key.ts @@ -0,0 +1,2 @@ +export const CONFIG_VARIABLES_METADATA_DECORATOR_KEY = + 'config-variables-metadata' as const; diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts new file mode 100644 index 00000000000..a84065b43d0 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/constants/config-variables-metadata-decorator-names-key.ts @@ -0,0 +1,2 @@ +export const CONFIG_VARIABLES_METADATA_DECORATOR_NAMES_KEY = + 'config-variable-names' as const; diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/assert-or-warn.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/assert-or-warn.decorator.spec.ts similarity index 81% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/assert-or-warn.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/assert-or-warn.decorator.spec.ts index 7479e0237a7..c123aea8724 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/assert-or-warn.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/assert-or-warn.decorator.spec.ts @@ -1,19 +1,19 @@ -import 'reflect-metadata'; -import { IsString, validateSync } from 'class-validator'; import { plainToClass } from 'class-transformer'; +import { IsString, validateSync } from 'class-validator'; +import 'reflect-metadata'; -import { AssertOrWarn } from 'src/engine/core-modules/environment/decorators/assert-or-warn.decorator'; +import { AssertOrWarn } from 'src/engine/core-modules/twenty-config/decorators/assert-or-warn.decorator'; describe('AssertOrWarn Decorator', () => { it('should pass validation if the condition is met', () => { - class EnvironmentVariables { + class ConfigVariables { @AssertOrWarn((object, value) => value > 10, { message: 'Value should be higher than 10', }) someProperty!: number; } - const validatedConfig = plainToClass(EnvironmentVariables, { + const validatedConfig = plainToClass(ConfigVariables, { someProperty: 15, }); @@ -23,14 +23,14 @@ describe('AssertOrWarn Decorator', () => { }); it('should provide a warning message if the condition is not met', () => { - class EnvironmentVariables { + class ConfigVariables { @AssertOrWarn((object, value) => value > 10, { message: 'Value should be higher than 10', }) someProperty!: number; } - const validatedConfig = plainToClass(EnvironmentVariables, { + const validatedConfig = plainToClass(ConfigVariables, { someProperty: 9, }); @@ -43,7 +43,7 @@ describe('AssertOrWarn Decorator', () => { }); it('should not impact errors if the condition is not met', () => { - class EnvironmentVariables { + class ConfigVariables { @IsString() unit: string; @@ -56,7 +56,7 @@ describe('AssertOrWarn Decorator', () => { duration!: number; } - const validatedConfig = plainToClass(EnvironmentVariables, { + const validatedConfig = plainToClass(ConfigVariables, { duration: 1731944140876000, unit: 's', }); diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts similarity index 93% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts index a35e03676ea..4cd656dff4a 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-log-level-array.decorator.spec.ts @@ -1,6 +1,6 @@ import { plainToClass } from 'class-transformer'; -import { CastToLogLevelArray } from 'src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator'; +import { CastToLogLevelArray } from 'src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator'; class TestClass { @CastToLogLevelArray() diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-positive-number.decorator.spec.ts similarity index 92% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-positive-number.decorator.spec.ts index cf302e0fd7c..12a0914dc51 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/__tests__/cast-to-positive-number.decorator.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/__tests__/cast-to-positive-number.decorator.spec.ts @@ -1,6 +1,6 @@ import { plainToClass } from 'class-transformer'; -import { CastToPositiveNumber } from 'src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator'; +import { CastToPositiveNumber } from 'src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator'; class TestClass { @CastToPositiveNumber() diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/assert-or-warn.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/assert-or-warn.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/assert-or-warn.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/assert-or-warn.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-boolean.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-boolean.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-boolean.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-boolean.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-log-level-array.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-log-level-array.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-meter-driver.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-meter-driver.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-meter-driver.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-meter-driver.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-positive-number.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-positive-number.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-string-array.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-string-array.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/cast-to-string-array.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/cast-to-string-array.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator.ts similarity index 58% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator.ts index 3297df9c268..5f84c9da83f 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator.ts @@ -1,29 +1,28 @@ import { registerDecorator, ValidationOptions } from 'class-validator'; -import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum'; +import { ConfigVariablesGroup } from 'src/engine/core-modules/twenty-config/enums/config-variables-group.enum'; import { TypedReflect } from 'src/utils/typed-reflect'; -export interface EnvironmentVariablesMetadataOptions { - group: EnvironmentVariablesGroup; +export interface ConfigVariablesMetadataOptions { + group: ConfigVariablesGroup; description: string; - sensitive?: boolean; + isSensitive?: boolean; } -export type EnvironmentVariablesMetadataMap = { - [key: string]: EnvironmentVariablesMetadataOptions; +export type ConfigVariablesMetadataMap = { + [key: string]: ConfigVariablesMetadataOptions; }; -export function EnvironmentVariablesMetadata( - options: EnvironmentVariablesMetadataOptions, +export function ConfigVariablesMetadata( + options: ConfigVariablesMetadataOptions, validationOptions?: ValidationOptions, ): PropertyDecorator { return (target: object, propertyKey: string | symbol) => { - const existingMetadata: EnvironmentVariablesMetadataMap = - TypedReflect.getMetadata('environment-variables', target.constructor) ?? - {}; + const existingMetadata: ConfigVariablesMetadataMap = + TypedReflect.getMetadata('config-variables', target.constructor) ?? {}; TypedReflect.defineMetadata( - 'environment-variables', + 'config-variables', { ...existingMetadata, [propertyKey.toString()]: options, diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-aws-region.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-aws-region.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-aws-region.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-aws-region.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-duration.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-duration.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-duration.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-duration.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-optional-or-empty-string.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-optional-or-empty-string.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-optional-or-empty-string.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-optional-or-empty-string.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-strictly-lower-than.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-strictly-lower-than.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-strictly-lower-than.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/decorators/is-twenty-semver.decorator.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-twenty-semver.decorator.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/decorators/is-twenty-semver.decorator.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/decorators/is-twenty-semver.decorator.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-group.enum.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-group.enum.ts similarity index 93% rename from packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-group.enum.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-group.enum.ts index 1019031a66f..d356499e45d 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-group.enum.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-group.enum.ts @@ -1,4 +1,4 @@ -export enum EnvironmentVariablesGroup { +export enum ConfigVariablesGroup { ServerConfig = 'server-config', RateLimiting = 'rate-limiting', StorageConfig = 'storage-config', diff --git a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum.ts similarity index 57% rename from packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum.ts index cbbeb6ccaa8..93dba5863ab 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum.ts @@ -1,4 +1,4 @@ -export enum EnvironmentVariablesMaskingStrategies { +export enum ConfigVariablesMaskingStrategies { LAST_N_CHARS = 'LAST_N_CHARS', HIDE_PASSWORD = 'HIDE_PASSWORD', } diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/environment.service.spec.ts similarity index 65% rename from packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/environment.service.spec.ts index 1fa526b5821..977c67c7818 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/environment.service.spec.ts @@ -1,17 +1,17 @@ import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; -import { EnvironmentVariables } from 'src/engine/core-modules/environment/environment-variables'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; -describe('EnvironmentService', () => { - let service: EnvironmentService; +describe('TwentyConfigService', () => { + let service: TwentyConfigService; let configService: ConfigService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ - EnvironmentService, + TwentyConfigService, { provide: ConfigService, useValue: { @@ -21,10 +21,10 @@ describe('EnvironmentService', () => { ], }).compile(); - service = module.get(EnvironmentService); + service = module.get(TwentyConfigService); configService = module.get(ConfigService); - Reflect.defineMetadata('environment-variables', {}, EnvironmentVariables); + Reflect.defineMetadata('config-variables', {}, ConfigVariables); }); it('should be defined', () => { @@ -32,13 +32,13 @@ describe('EnvironmentService', () => { }); describe('getAll()', () => { - it('should return empty object when no environment variables are defined', () => { + it('should return empty object when no config variables are defined', () => { const result = service.getAll(); expect(result).toEqual({}); }); - it('should return environment variables with their metadata', () => { + it('should return config variables with their metadata', () => { const mockMetadata = { TEST_VAR: { title: 'Test Var', @@ -46,11 +46,7 @@ describe('EnvironmentService', () => { }, }; - Reflect.defineMetadata( - 'environment-variables', - mockMetadata, - EnvironmentVariables, - ); + Reflect.defineMetadata('config-variables', mockMetadata, ConfigVariables); jest.spyOn(configService, 'get').mockReturnValue('test-value'); @@ -73,11 +69,7 @@ describe('EnvironmentService', () => { }, }; - Reflect.defineMetadata( - 'environment-variables', - mockMetadata, - EnvironmentVariables, - ); + Reflect.defineMetadata('config-variables', mockMetadata, ConfigVariables); jest.spyOn(configService, 'get').mockReturnValue('super-secret-value'); diff --git a/packages/twenty-server/src/engine/core-modules/environment/interfaces/aws-region.interface.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/aws-region.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/interfaces/aws-region.interface.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/aws-region.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/interfaces/node-environment.interface.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/node-environment.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/interfaces/node-environment.interface.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/node-environment.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/interfaces/support.interface.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/support.interface.ts similarity index 100% rename from packages/twenty-server/src/engine/core-modules/environment/interfaces/support.interface.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/interfaces/support.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module-definition.ts similarity index 86% rename from packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module-definition.ts index 242e2ef3cdd..fd8a52c5104 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.module-definition.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module-definition.ts @@ -2,7 +2,7 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder({ - moduleName: 'Environment', + moduleName: 'TwentyConfig', }) .setClassMethodName('forRoot') .build(); diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment.module.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module.ts similarity index 50% rename from packages/twenty-server/src/engine/core-modules/environment/environment.module.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module.ts index 841f2b0bbf8..2083625d83f 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment.module.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.module.ts @@ -1,9 +1,9 @@ import { Global, Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; -import { validate } from 'src/engine/core-modules/environment/environment-variables'; -import { ConfigurableModuleClass } from 'src/engine/core-modules/environment/environment.module-definition'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { validate } from 'src/engine/core-modules/twenty-config/config-variables'; +import { ConfigurableModuleClass } from 'src/engine/core-modules/twenty-config/twenty-config.module-definition'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Global() @Module({ @@ -15,7 +15,7 @@ import { EnvironmentService } from 'src/engine/core-modules/environment/environm envFilePath: process.env.NODE_ENV === 'test' ? '.env.test' : '.env', }), ], - providers: [EnvironmentService], - exports: [EnvironmentService], + providers: [TwentyConfigService], + exports: [TwentyConfigService], }) -export class EnvironmentModule extends ConfigurableModuleClass {} +export class TwentyConfigModule extends ConfigurableModuleClass {} diff --git a/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts new file mode 100644 index 00000000000..6dd527991c2 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/twenty-config.service.ts @@ -0,0 +1,73 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +import { ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables'; +import { CONFIG_VARIABLES_MASKING_CONFIG } from 'src/engine/core-modules/twenty-config/constants/config-variables-masking-config'; +import { ConfigVariablesMetadataOptions } from 'src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator'; +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; +import { configVariableMaskSensitiveData } from 'src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util'; +import { TypedReflect } from 'src/utils/typed-reflect'; + +@Injectable() +export class TwentyConfigService { + constructor(private readonly configService: ConfigService) {} + + get(key: T): ConfigVariables[T] { + return this.configService.get( + key, + new ConfigVariables()[key], + ); + } + + getAll(): Record< + string, + { + value: ConfigVariables[keyof ConfigVariables]; + metadata: ConfigVariablesMetadataOptions; + } + > { + const result: Record< + string, + { + value: ConfigVariables[keyof ConfigVariables]; + metadata: ConfigVariablesMetadataOptions; + } + > = {}; + + const configVars = new ConfigVariables(); + const metadata = + TypedReflect.getMetadata('config-variables', ConfigVariables) ?? {}; + + Object.entries(metadata).forEach(([key, envMetadata]) => { + let value = + this.configService.get(key) ?? + configVars[key as keyof ConfigVariables] ?? + ''; + + if (typeof value === 'string' && key in CONFIG_VARIABLES_MASKING_CONFIG) { + const varMaskingConfig = + CONFIG_VARIABLES_MASKING_CONFIG[ + key as keyof typeof CONFIG_VARIABLES_MASKING_CONFIG + ]; + const options = + varMaskingConfig.strategy === + ConfigVariablesMaskingStrategies.LAST_N_CHARS + ? { chars: varMaskingConfig.chars } + : undefined; + + value = configVariableMaskSensitiveData( + value, + varMaskingConfig.strategy, + { ...options, variableName: key }, + ); + } + + result[key] = { + value, + metadata: envMetadata, + }; + }); + + return result; + } +} diff --git a/packages/twenty-server/src/engine/core-modules/environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts similarity index 53% rename from packages/twenty-server/src/engine/core-modules/environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts index 9d84c25e34d..28c0427b09f 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/utils/__tests__/environment-variable-mask-sensitive-data.util.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/__tests__/config-variable-mask-sensitive-data.util.spec.ts @@ -1,21 +1,21 @@ -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; -import { environmentVariableMaskSensitiveData } from 'src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util'; +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; +import { configVariableMaskSensitiveData } from 'src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util'; -describe('environmentVariableMaskSensitiveData', () => { +describe('configVariableMaskSensitiveData', () => { describe('LAST_N_CHARS strategy', () => { it('should mask all but the last 5 characters by default', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'mysecretvalue123', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBe('********ue123'); }); it('should mask all but the specified number of characters', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'mysecretvalue123', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, { chars: 3 }, ); @@ -23,9 +23,9 @@ describe('environmentVariableMaskSensitiveData', () => { }); it('should return all asterisks if value is shorter than mask length', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( '123', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, { chars: 5 }, ); @@ -33,9 +33,9 @@ describe('environmentVariableMaskSensitiveData', () => { }); it('should handle empty string', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( '', - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBe(''); @@ -44,18 +44,18 @@ describe('environmentVariableMaskSensitiveData', () => { describe('HIDE_PASSWORD strategy', () => { it('should mask password in URL', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'postgresql://user:password123@localhost:5432/db', - EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, + ConfigVariablesMaskingStrategies.HIDE_PASSWORD, ); expect(result).toBe('postgresql://********:********@localhost:5432/db'); }); it('should handle URL without password', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 'postgresql://localhost:5432/db', - EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, + ConfigVariablesMaskingStrategies.HIDE_PASSWORD, ); expect(result).toBe('postgresql://localhost:5432/db'); @@ -63,9 +63,9 @@ describe('environmentVariableMaskSensitiveData', () => { it('should throw error for invalid URLs', () => { expect(() => - environmentVariableMaskSensitiveData( + configVariableMaskSensitiveData( 'not-a-url', - EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD, + ConfigVariablesMaskingStrategies.HIDE_PASSWORD, { variableName: 'TEST_URL' }, ), ).toThrow( @@ -76,27 +76,27 @@ describe('environmentVariableMaskSensitiveData', () => { describe('edge cases', () => { it('should handle null value', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( null as any, - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBeNull(); }); it('should handle undefined value', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( undefined as any, - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBeUndefined(); }); it('should handle non-string value', () => { - const result = environmentVariableMaskSensitiveData( + const result = configVariableMaskSensitiveData( 123 as any, - EnvironmentVariablesMaskingStrategies.LAST_N_CHARS, + ConfigVariablesMaskingStrategies.LAST_N_CHARS, ); expect(result).toBe(123); diff --git a/packages/twenty-server/src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util.ts b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util.ts similarity index 56% rename from packages/twenty-server/src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util.ts rename to packages/twenty-server/src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util.ts index 4497d55e5ca..4f60a2de1b9 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/utils/environment-variable-mask-sensitive-data.util.ts +++ b/packages/twenty-server/src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util.ts @@ -1,19 +1,19 @@ -import { EnvironmentVariablesMaskingStrategies } from 'src/engine/core-modules/environment/enums/environment-variables-masking-strategies.enum'; +import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum'; -export const environmentVariableMaskSensitiveData = ( +export const configVariableMaskSensitiveData = ( value: string, - strategy: EnvironmentVariablesMaskingStrategies, + strategy: ConfigVariablesMaskingStrategies, options?: { chars?: number; variableName?: string }, ): string => { if (!value || typeof value !== 'string') return value; switch (strategy) { - case EnvironmentVariablesMaskingStrategies.LAST_N_CHARS: { + case ConfigVariablesMaskingStrategies.LAST_N_CHARS: { const n = Math.max(1, options?.chars ?? 5); return value.length > n ? `********${value.slice(-n)}` : '********'; } - case EnvironmentVariablesMaskingStrategies.HIDE_PASSWORD: { + case ConfigVariablesMaskingStrategies.HIDE_PASSWORD: { try { const url = new URL(value); @@ -27,7 +27,7 @@ export const environmentVariableMaskSensitiveData = ( return url.toString(); } catch { throw new Error( - `Invalid URL format for ${options?.variableName || 'environment variable'} in HIDE_PASSWORD masking strategy`, + `Invalid URL format for ${options?.variableName || 'config variable'} in HIDE_PASSWORD masking strategy`, ); } } diff --git a/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts b/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts index 9ee22996e2a..3a07d51906d 100644 --- a/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/user/user.resolver.ts @@ -17,8 +17,8 @@ import { PermissionsOnAllObjectRecords } from 'twenty-shared/constants'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; import { In, Repository } from 'typeorm'; -import { SupportDriver } from 'src/engine/core-modules/environment/interfaces/support.interface'; import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; +import { SupportDriver } from 'src/engine/core-modules/twenty-config/interfaces/support.interface'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; import { @@ -26,7 +26,6 @@ import { AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileService } from 'src/engine/core-modules/file/services/file.service'; import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum'; @@ -34,6 +33,7 @@ import { OnboardingService, OnboardingStepKeys, } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @@ -70,7 +70,7 @@ export class UserResolver { @InjectRepository(User, 'core') private readonly userRepository: Repository, private readonly userService: UserService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly fileUploadService: FileUploadService, private readonly onboardingService: OnboardingService, private readonly userVarService: UserVarsService, @@ -285,10 +285,12 @@ export class UserResolver { nullable: true, }) supportUserHash(@Parent() parent: User): string | null { - if (this.environmentService.get('SUPPORT_DRIVER') !== SupportDriver.Front) { + if ( + this.twentyConfigService.get('SUPPORT_DRIVER') !== SupportDriver.Front + ) { return null; } - const key = this.environmentService.get('SUPPORT_FRONT_HMAC_KEY'); + const key = this.twentyConfigService.get('SUPPORT_FRONT_HMAC_KEY'); return getHMACKey(parent.email, key); } diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts index 7c176c618ff..ef1dcd315e1 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.spec.ts @@ -7,15 +7,15 @@ import { AppToken, AppTokenType, } from 'src/engine/core-modules/app-token/app-token.entity'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { WorkspaceInvitationException } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.exception'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceInvitationService } from './workspace-invitation.service'; @@ -26,7 +26,7 @@ describe('WorkspaceInvitationService', () => { let service: WorkspaceInvitationService; let appTokenRepository: Repository; let userWorkspaceRepository: Repository; - let environmentService: EnvironmentService; + let twentyConfigService: TwentyConfigService; let emailService: EmailService; let onboardingService: OnboardingService; @@ -55,7 +55,7 @@ describe('WorkspaceInvitationService', () => { }, }, { - provide: EnvironmentService, + provide: TwentyConfigService, useValue: { get: jest.fn(), }, @@ -94,7 +94,7 @@ describe('WorkspaceInvitationService', () => { userWorkspaceRepository = module.get>( getRepositoryToken(UserWorkspace, 'core'), ); - environmentService = module.get(EnvironmentService); + twentyConfigService = module.get(TwentyConfigService); emailService = module.get(EmailService); onboardingService = module.get(OnboardingService); }); @@ -156,7 +156,7 @@ describe('WorkspaceInvitationService', () => { type: AppTokenType.InvitationToken, } as AppToken); jest - .spyOn(environmentService, 'get') + .spyOn(twentyConfigService, 'get') .mockReturnValue('http://localhost:3000'); jest.spyOn(emailService, 'send').mockResolvedValue({} as any); jest diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts index 1d3f67f84b3..c361bd4738b 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts @@ -22,8 +22,8 @@ import { } from 'src/engine/core-modules/auth/auth.exception'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { SendInvitationsOutput } from 'src/engine/core-modules/workspace-invitation/dtos/send-invitations.output'; @@ -42,7 +42,7 @@ export class WorkspaceInvitationService { private readonly appTokenRepository: Repository, @InjectRepository(UserWorkspace, 'core') private readonly userWorkspaceRepository: Repository, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly emailService: EmailService, private readonly onboardingService: OnboardingService, private readonly domainManagerService: DomainManagerService, @@ -300,7 +300,7 @@ export class WorkspaceInvitationService { firstName: sender.firstName, lastName: sender.lastName, }, - serverUrl: this.environmentService.get('SERVER_URL'), + serverUrl: this.twentyConfigService.get('SERVER_URL'), locale: sender.locale as keyof typeof APP_LOCALES, }; @@ -313,7 +313,7 @@ export class WorkspaceInvitationService { i18n.activate(sender.locale); await this.emailService.send({ - from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + from: `${sender.firstName} ${sender.lastName} (via Twenty) <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, to: invitation.value.email, subject: t`Join your team on Twenty`, text, @@ -360,7 +360,7 @@ export class WorkspaceInvitationService { } async generateInvitationToken(workspaceId: string, email: string) { - const expiresIn = this.environmentService.get( + const expiresIn = this.twentyConfigService.get( 'INVITATION_TOKEN_EXPIRES_IN', ); diff --git a/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts b/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts index 46cbb3343d1..b1ce5d021fe 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/__tests__/workspace.service.spec.ts @@ -8,13 +8,13 @@ import { BillingService } from 'src/engine/core-modules/billing/services/billing import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; @@ -81,7 +81,7 @@ describe('WorkspaceService', () => { UserService, DomainManagerService, CustomDomainService, - EnvironmentService, + TwentyConfigService, EmailService, OnboardingService, WorkspaceInvitationService, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts index 1fb1cb8cc42..84b1dc9e3e2 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts @@ -13,7 +13,6 @@ import { BillingSubscriptionService } from 'src/engine/core-modules/billing/serv import { BillingService } from 'src/engine/core-modules/billing/services/billing.service'; import { CustomDomainService } from 'src/engine/core-modules/domain-manager/services/custom-domain.service'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { @@ -23,6 +22,7 @@ import { import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -63,7 +63,7 @@ export class WorkspaceService extends TypeOrmQueryService { private readonly billingSubscriptionService: BillingSubscriptionService, private readonly billingService: BillingService, private readonly userWorkspaceService: UserWorkspaceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly domainManagerService: DomainManagerService, private readonly exceptionHandlerService: ExceptionHandlerService, private readonly permissionsService: PermissionsService, @@ -95,7 +95,7 @@ export class WorkspaceService extends TypeOrmQueryService { if ( !subdomainAvailable || - this.environmentService.get('DEFAULT_SUBDOMAIN') === newSubdomain + this.twentyConfigService.get('DEFAULT_SUBDOMAIN') === newSubdomain ) { throw new WorkspaceException( 'Subdomain already taken', @@ -189,9 +189,9 @@ export class WorkspaceService extends TypeOrmQueryService { } const authProvidersBySystem = { - google: this.environmentService.get('AUTH_GOOGLE_ENABLED'), - password: this.environmentService.get('AUTH_PASSWORD_ENABLED'), - microsoft: this.environmentService.get('AUTH_MICROSOFT_ENABLED'), + google: this.twentyConfigService.get('AUTH_GOOGLE_ENABLED'), + password: this.twentyConfigService.get('AUTH_PASSWORD_ENABLED'), + microsoft: this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED'), }; if (payload.isGoogleAuthEnabled && !authProvidersBySystem.google) { @@ -267,7 +267,7 @@ export class WorkspaceService extends TypeOrmQueryService { }); await this.userWorkspaceService.createWorkspaceMember(workspace.id, user); - const appVersion = this.environmentService.get('APP_VERSION'); + const appVersion = this.twentyConfigService.get('APP_VERSION'); await this.workspaceRepository.update(workspace.id, { displayName: data.displayName, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts index ac6388fd9f3..3aa5c9c7f62 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts @@ -21,12 +21,12 @@ import { BillingSubscription } from 'src/engine/core-modules/billing/entities/bi import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service'; import { CustomDomainValidRecords } from 'src/engine/core-modules/domain-manager/dtos/custom-domain-valid-records'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { FileService } from 'src/engine/core-modules/file/services/file.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input'; @@ -68,7 +68,7 @@ export class WorkspaceResolver { private readonly workspaceService: WorkspaceService, private readonly domainManagerService: DomainManagerService, private readonly userWorkspaceService: UserWorkspaceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly fileUploadService: FileUploadService, private readonly fileService: FileService, private readonly billingSubscriptionService: BillingSubscriptionService, @@ -184,7 +184,7 @@ export class WorkspaceResolver { async billingSubscriptions( @Parent() workspace: Workspace, ): Promise { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return []; } @@ -213,7 +213,7 @@ export class WorkspaceResolver { async currentBillingSubscription( @Parent() workspace: Workspace, ): Promise { - if (!this.environmentService.get('IS_BILLING_ENABLED')) { + if (!this.twentyConfigService.get('IS_BILLING_ENABLED')) { return; } @@ -248,7 +248,7 @@ export class WorkspaceResolver { @ResolveField(() => Boolean) hasValidEnterpriseKey(): boolean { - return isDefined(this.environmentService.get('ENTERPRISE_KEY')); + return isDefined(this.twentyConfigService.get('ENTERPRISE_KEY')); } @ResolveField(() => WorkspaceUrls) @@ -260,7 +260,7 @@ export class WorkspaceResolver { isGoogleAuthEnabled(@Parent() workspace: Workspace) { return ( workspace.isGoogleAuthEnabled && - this.environmentService.get('AUTH_GOOGLE_ENABLED') + this.twentyConfigService.get('AUTH_GOOGLE_ENABLED') ); } @@ -268,7 +268,7 @@ export class WorkspaceResolver { isMicrosoftAuthEnabled(@Parent() workspace: Workspace) { return ( workspace.isMicrosoftAuthEnabled && - this.environmentService.get('AUTH_MICROSOFT_ENABLED') + this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED') ); } @@ -276,7 +276,7 @@ export class WorkspaceResolver { isPasswordAuthEnabled(@Parent() workspace: Workspace) { return ( workspace.isPasswordAuthEnabled && - this.environmentService.get('AUTH_PASSWORD_ENABLED') + this.twentyConfigService.get('AUTH_PASSWORD_ENABLED') ); } @@ -315,10 +315,10 @@ export class WorkspaceResolver { } const systemEnabledProviders: AuthProviders = { - google: this.environmentService.get('AUTH_GOOGLE_ENABLED'), + google: this.twentyConfigService.get('AUTH_GOOGLE_ENABLED'), magicLink: false, - password: this.environmentService.get('AUTH_PASSWORD_ENABLED'), - microsoft: this.environmentService.get('AUTH_MICROSOFT_ENABLED'), + password: this.twentyConfigService.get('AUTH_PASSWORD_ENABLED'), + microsoft: this.twentyConfigService.get('AUTH_MICROSOFT_ENABLED'), sso: [], }; diff --git a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts index 9fa5d96a3dd..682cc0ddee6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/serverless-function/serverless-function.service.ts @@ -4,14 +4,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { basename, dirname, join } from 'path'; import deepEqual from 'deep-equal'; -import { IsNull, Not, Repository } from 'typeorm'; import { isDefined } from 'twenty-shared/utils'; +import { IsNull, Not, Repository } from 'typeorm'; import { FileStorageExceptionCode } from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; import { ServerlessExecuteResult } from 'src/engine/core-modules/serverless/drivers/interfaces/serverless-driver.interface'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { readFileContent } from 'src/engine/core-modules/file-storage/utils/read-file-content'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; @@ -25,6 +24,7 @@ import { getLayerDependencies } from 'src/engine/core-modules/serverless/drivers import { ServerlessService } from 'src/engine/core-modules/serverless/serverless.service'; import { getServerlessFolder } from 'src/engine/core-modules/serverless/utils/serverless-get-folder.utils'; import { ThrottlerService } from 'src/engine/core-modules/throttler/throttler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { CreateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/create-serverless-function.input'; import { UpdateServerlessFunctionInput } from 'src/engine/metadata-modules/serverless-function/dtos/update-serverless-function.input'; import { @@ -44,7 +44,7 @@ export class ServerlessFunctionService { @InjectRepository(ServerlessFunctionEntity, 'metadata') private readonly serverlessFunctionRepository: Repository, private readonly throttlerService: ThrottlerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly analyticsService: AnalyticsService, @InjectMessageQueue(MessageQueue.serverlessFunctionQueue) private readonly messageQueueService: MessageQueueService, @@ -392,8 +392,8 @@ export class ServerlessFunctionService { try { await this.throttlerService.throttle( `${workspaceId}-serverless-function-execution`, - this.environmentService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_LIMIT'), - this.environmentService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_TTL'), + this.twentyConfigService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_LIMIT'), + this.twentyConfigService.get('SERVERLESS_FUNCTION_EXEC_THROTTLE_TTL'), ); } catch (error) { throw new ServerlessFunctionException( diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts index 2260994fecc..baf4808e96c 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/workspace-datasource.factory.ts @@ -2,9 +2,9 @@ import { Injectable, Logger } from '@nestjs/common'; import { EntitySchema } from 'typeorm'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; @@ -24,7 +24,7 @@ export class WorkspaceDatasourceFactory { constructor( private readonly dataSourceService: DataSourceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService, private readonly entitySchemaFactory: EntitySchemaFactory, @@ -124,16 +124,16 @@ export class WorkspaceDatasourceFactory { { url: dataSourceMetadata.url ?? - this.environmentService.get('PG_DATABASE_URL'), + this.twentyConfigService.get('PG_DATABASE_URL'), type: 'postgres', logging: - this.environmentService.get('NODE_ENV') === + this.twentyConfigService.get('NODE_ENV') === NodeEnvironment.development ? ['query', 'error'] : ['error'], schema: dataSourceMetadata.schema, entities: cachedEntitySchemas, - ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED') + ssl: this.twentyConfigService.get('PG_SSL_ALLOW_SELF_SIGNED') ? { rejectUnauthorized: false, } diff --git a/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts b/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts index 613b0b38106..32760517217 100644 --- a/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts +++ b/packages/twenty-server/src/engine/utils/global-exception-handler.util.ts @@ -2,9 +2,9 @@ import { HttpException } from '@nestjs/common'; import { GraphQLError } from 'graphql'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; import { ExceptionHandlerWorkspace } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-workspace.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts index db5c638e036..4afccef6532 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/services/cleaner.workspace-service.ts @@ -15,7 +15,7 @@ import { In, Repository } from 'typeorm'; import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { EmailService } from 'src/engine/core-modules/email/email.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserService } from 'src/engine/core-modules/user/services/user.service'; import { UserVarsService } from 'src/engine/core-modules/user/user-vars/services/user-vars.service'; @@ -39,7 +39,7 @@ export class CleanerWorkspaceService { constructor( private readonly workspaceService: WorkspaceService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly userVarsService: UserVarsService, private readonly userService: UserService, private readonly emailService: EmailService, @@ -51,18 +51,19 @@ export class CleanerWorkspaceService { @InjectRepository(UserWorkspace, 'core') private readonly userWorkspaceRepository: Repository, ) { - this.inactiveDaysBeforeSoftDelete = this.environmentService.get( + this.inactiveDaysBeforeSoftDelete = this.twentyConfigService.get( 'WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION', ); - this.inactiveDaysBeforeDelete = this.environmentService.get( + this.inactiveDaysBeforeDelete = this.twentyConfigService.get( 'WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION', ); - this.inactiveDaysBeforeWarn = this.environmentService.get( + this.inactiveDaysBeforeWarn = this.twentyConfigService.get( 'WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION', ); - this.maxNumberOfWorkspacesDeletedPerExecution = this.environmentService.get( - 'MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION', - ); + this.maxNumberOfWorkspacesDeletedPerExecution = + this.twentyConfigService.get( + 'MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION', + ); } async computeWorkspaceBillingInactivity( @@ -128,9 +129,9 @@ export class CleanerWorkspaceService { this.emailService.send({ to: workspaceMember.userEmail, - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, subject: t`Action needed to prevent workspace deletion`, html, text, @@ -202,9 +203,9 @@ export class CleanerWorkspaceService { this.emailService.send({ to: workspaceMember.userEmail, - from: `${this.environmentService.get( + from: `${this.twentyConfigService.get( 'EMAIL_FROM_NAME', - )} <${this.environmentService.get('EMAIL_FROM_ADDRESS')}>`, + )} <${this.twentyConfigService.get('EMAIL_FROM_ADDRESS')}>`, subject: 'Your workspace has been deleted', html, text, diff --git a/packages/twenty-server/src/instrument.ts b/packages/twenty-server/src/instrument.ts index 3ec3f692ba6..e2f542e0aae 100644 --- a/packages/twenty-server/src/instrument.ts +++ b/packages/twenty-server/src/instrument.ts @@ -10,7 +10,7 @@ import { import * as Sentry from '@sentry/node'; import { nodeProfilingIntegration } from '@sentry/profiling-node'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; import { ExceptionHandlerDriver } from 'src/engine/core-modules/exception-handler/interfaces'; import { MeterDriver } from 'src/engine/core-modules/metrics/types/meter-driver.type'; diff --git a/packages/twenty-server/src/main.ts b/packages/twenty-server/src/main.ts index f884512429a..d52856e8bcd 100644 --- a/packages/twenty-server/src/main.ts +++ b/packages/twenty-server/src/main.ts @@ -9,11 +9,11 @@ import { useContainer, ValidationError } from 'class-validator'; import session from 'express-session'; import { graphqlUploadExpress } from 'graphql-upload'; -import { NodeEnvironment } from 'src/engine/core-modules/environment/interfaces/node-environment.interface'; +import { NodeEnvironment } from 'src/engine/core-modules/twenty-config/interfaces/node-environment.interface'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { LoggerService } from 'src/engine/core-modules/logger/logger.service'; import { getSessionStorageOptions } from 'src/engine/core-modules/session-storage/session-storage.module-factory'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { UnhandledExceptionFilter } from 'src/filters/unhandled-exception.filter'; import { AppModule } from './app.module'; @@ -38,9 +38,9 @@ const bootstrap = async () => { : {}), }); const logger = app.get(LoggerService); - const environmentService = app.get(EnvironmentService); + const twentyConfigService = app.get(TwentyConfigService); - app.use(session(getSessionStorageOptions(environmentService))); + app.use(session(getSessionStorageOptions(twentyConfigService))); // TODO: Double check this as it's not working for now, it's going to be helpful for durable trees in twenty "orm" // // Apply context id strategy for durable trees @@ -87,7 +87,7 @@ const bootstrap = async () => { // Inject the server url in the frontend page generateFrontConfig(); - await app.listen(environmentService.get('NODE_PORT')); + await app.listen(twentyConfigService.get('NODE_PORT')); }; bootstrap(); diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts index d76a6642df6..5150ef3f8dc 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/google-calendar-driver.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { GoogleCalendarClientProvider } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/providers/google-calendar.provider'; import { GoogleCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/services/google-calendar-get-events.service'; import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module'; @Module({ - imports: [EnvironmentModule, OAuth2ClientManagerModule], + imports: [TwentyConfigModule, OAuth2ClientManagerModule], providers: [GoogleCalendarClientProvider, GoogleCalendarGetEventsService], exports: [GoogleCalendarGetEventsService], }) diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts index def97bfb69a..d6635421e39 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/microsoft-calendar-driver.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/services/microsoft-calendar-get-events.service'; import { MicrosoftCalendarImportEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/services/microsoft-calendar-import-events.service'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; @Module({ - imports: [EnvironmentModule], + imports: [TwentyConfigModule], providers: [ MicrosoftCalendarGetEventsService, MicrosoftCalendarImportEventsService, diff --git a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts index e5020f25427..d5c7cb89ce4 100644 --- a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts +++ b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service.ts @@ -3,15 +3,15 @@ import { Injectable } from '@nestjs/common'; import { OAuth2Client } from 'google-auth-library'; import { google } from 'googleapis'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class GoogleOAuth2ClientManagerService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} public async getOAuth2Client(refreshToken: string): Promise { - const gmailClientId = this.environmentService.get('AUTH_GOOGLE_CLIENT_ID'); - const gmailClientSecret = this.environmentService.get( + const gmailClientId = this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'); + const gmailClientSecret = this.twentyConfigService.get( 'AUTH_GOOGLE_CLIENT_SECRET', ); diff --git a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts index 7f4d263345c..1a1c24b0adf 100644 --- a/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts +++ b/packages/twenty-server/src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service.ts @@ -6,11 +6,11 @@ import { Client, } from '@microsoft/microsoft-graph-client'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @Injectable() export class MicrosoftOAuth2ClientManagerService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} public async getOAuth2Client(refreshToken: string): Promise { const authProvider: AuthProvider = async ( @@ -21,13 +21,13 @@ export class MicrosoftOAuth2ClientManagerService { urlData.append( 'client_id', - this.environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), + this.twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), ); urlData.append('scope', 'https://graph.microsoft.com/.default'); urlData.append('refresh_token', refreshToken); urlData.append( 'client_secret', - this.environmentService.get('AUTH_MICROSOFT_CLIENT_SECRET'), + this.twentyConfigService.get('AUTH_MICROSOFT_CLIENT_SECRET'), ); urlData.append('grant_type', 'refresh_token'); diff --git a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts index 7de5f4b00c8..2843ce491a4 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-access-token.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; import { z } from 'zod'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type GoogleTokens = { accessToken: string; @@ -18,14 +18,16 @@ interface GoogleRefreshTokenResponse { } @Injectable() export class GoogleAPIRefreshAccessTokenService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} async refreshAccessToken(refreshToken: string): Promise { const response = await axios.post( 'https://oauth2.googleapis.com/token', { - client_id: this.environmentService.get('AUTH_GOOGLE_CLIENT_ID'), - client_secret: this.environmentService.get('AUTH_GOOGLE_CLIENT_SECRET'), + client_id: this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'), + client_secret: this.twentyConfigService.get( + 'AUTH_GOOGLE_CLIENT_SECRET', + ), refresh_token: refreshToken, grant_type: 'refresh_token', }, diff --git a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts index 241aa8435f5..b560ab406f6 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service'; @Module({ - imports: [EnvironmentModule], + imports: [TwentyConfigModule], providers: [MicrosoftAPIRefreshAccessTokenService], exports: [MicrosoftAPIRefreshAccessTokenService], }) diff --git a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts index 0d71161274f..64054b23b00 100644 --- a/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts +++ b/packages/twenty-server/src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; import { z } from 'zod'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; export type MicrosoftTokens = { accessToken: string; @@ -20,14 +20,14 @@ interface MicrosoftRefreshTokenResponse { } @Injectable() export class MicrosoftAPIRefreshAccessTokenService { - constructor(private readonly environmentService: EnvironmentService) {} + constructor(private readonly twentyConfigService: TwentyConfigService) {} async refreshTokens(refreshToken: string): Promise { const response = await axios.post( 'https://login.microsoftonline.com/common/oauth2/v2.0/token', new URLSearchParams({ - client_id: this.environmentService.get('AUTH_MICROSOFT_CLIENT_ID'), - client_secret: this.environmentService.get( + client_id: this.twentyConfigService.get('AUTH_MICROSOFT_CLIENT_ID'), + client_secret: this.twentyConfigService.get( 'AUTH_MICROSOFT_CLIENT_SECRET', ), refresh_token: refreshToken, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts index 100db9787d4..f54c4c2e601 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts @@ -2,9 +2,9 @@ import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; @@ -24,7 +24,7 @@ import { MessageParticipantManagerModule } from 'src/modules/messaging/message-p HttpModule.register({ baseURL: 'https://www.googleapis.com/batch/gmail/v1', }), - EnvironmentModule, + TwentyConfigModule, ObjectMetadataRepositoryModule.forFeature([BlocklistWorkspaceEntity]), MessagingCommonModule, TypeOrmModule.forFeature([FeatureFlag], 'core'), diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts index 2c19db33f03..8835d9a1f35 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/messaging-microsoft-driver.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; @@ -16,7 +16,7 @@ import { MicrosoftGetMessageListService } from './services/microsoft-get-message @Module({ imports: [ - EnvironmentModule, + TwentyConfigModule, MessagingCommonModule, FeatureFlagModule, OAuth2ClientManagerModule, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts index f95d9947a0d..88bfa5a53ec 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service.dev.spec.ts @@ -3,7 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConnectedAccountProvider } from 'twenty-shared/types'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity'; @@ -28,7 +28,7 @@ xdescribe('Microsoft dev tests : get message list service', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessageListService, MicrosoftClientProvider, @@ -118,7 +118,7 @@ xdescribe('Microsoft dev tests : get full message list service for folders', () beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessageListService, MicrosoftClientProvider, @@ -207,7 +207,7 @@ xdescribe('Microsoft dev tests : get partial message list service for folders', beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessageListService, MicrosoftClientProvider, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts index 28b0a8cd04d..1010eb3f768 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.dev.spec.ts @@ -3,7 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConnectedAccountProvider } from 'twenty-shared/types'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; import { MicrosoftClientProvider } from 'src/modules/messaging/message-import-manager/drivers/microsoft/providers/microsoft-client.provider'; import { MicrosoftFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service'; @@ -23,7 +23,7 @@ xdescribe('Microsoft dev tests : get messages service', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessagesService, MicrosoftHandleErrorService, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts index a7c9774ad9b..afe372e39bb 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service.spec.ts @@ -3,7 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConnectedAccountProvider } from 'twenty-shared/types'; -import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module'; +import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module'; import { MicrosoftOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/microsoft/microsoft-oauth2-client-manager.service'; import { microsoftGraphBatchWithHtmlMessagesResponse, @@ -21,7 +21,7 @@ describe('Microsoft get messages service', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [EnvironmentModule.forRoot({})], + imports: [TwentyConfigModule.forRoot({})], providers: [ MicrosoftGetMessagesService, MicrosoftHandleErrorService, diff --git a/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts b/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts index d9455ed17bc..72007349073 100644 --- a/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts +++ b/packages/twenty-server/src/modules/messaging/monitoring/services/messaging-telemetry.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { AnalyticsService } from 'src/engine/core-modules/analytics/analytics.service'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; type MessagingTelemetryTrackInput = { eventName: string; @@ -16,7 +16,7 @@ type MessagingTelemetryTrackInput = { export class MessagingTelemetryService { constructor( private readonly analyticsService: AnalyticsService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, ) {} public async track({ diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts index 75ae7eb2ca1..0ebffda5bf2 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts @@ -1,10 +1,10 @@ import { Scope } from '@nestjs/common'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { ThrottlerService } from 'src/engine/core-modules/throttler/throttler.service'; +import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkflowRunStatus } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; @@ -30,7 +30,7 @@ export class RunWorkflowJob { private readonly workflowExecutorWorkspaceService: WorkflowExecutorWorkspaceService, private readonly workflowRunWorkspaceService: WorkflowRunWorkspaceService, private readonly throttlerService: ThrottlerService, - private readonly environmentService: EnvironmentService, + private readonly twentyConfigService: TwentyConfigService, private readonly twentyORMManager: TwentyORMManager, ) {} @@ -182,8 +182,8 @@ export class RunWorkflowJob { try { await this.throttlerService.throttle( `${workflowId}-workflow-execution`, - this.environmentService.get('WORKFLOW_EXEC_THROTTLE_LIMIT'), - this.environmentService.get('WORKFLOW_EXEC_THROTTLE_TTL'), + this.twentyConfigService.get('WORKFLOW_EXEC_THROTTLE_LIMIT'), + this.twentyConfigService.get('WORKFLOW_EXEC_THROTTLE_TTL'), ); } catch (error) { throw new WorkflowRunException( diff --git a/packages/twenty-server/src/utils/typed-reflect.ts b/packages/twenty-server/src/utils/typed-reflect.ts index 0e8f8e99fea..a871540f90b 100644 --- a/packages/twenty-server/src/utils/typed-reflect.ts +++ b/packages/twenty-server/src/utils/typed-reflect.ts @@ -3,7 +3,7 @@ import 'reflect-metadata'; import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; import { WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type'; -import { EnvironmentVariablesMetadataMap } from 'src/engine/core-modules/environment/decorators/environment-variables-metadata.decorator'; +import { ConfigVariablesMetadataMap } from 'src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator'; export interface ReflectMetadataTypeMap { ['workspace:is-nullable-metadata-args']: true; @@ -14,7 +14,7 @@ export interface ReflectMetadataTypeMap { ['workspace:is-deprecated-field-metadata-args']: true; ['workspace:is-unique-metadata-args']: true; ['workspace:duplicate-criteria-metadata-args']: WorkspaceEntityDuplicateCriteria[]; - ['environment-variables']: EnvironmentVariablesMetadataMap; + ['config-variables']: ConfigVariablesMetadataMap; ['workspace:is-searchable-metadata-args']: boolean; } diff --git a/packages/twenty-utils/dangerfile.ts b/packages/twenty-utils/dangerfile.ts index 424fff73fd3..df7a785319c 100644 --- a/packages/twenty-utils/dangerfile.ts +++ b/packages/twenty-utils/dangerfile.ts @@ -18,14 +18,14 @@ if (packageChanged && !lockfileChanged) { warn(`${message} - ${idea}`); } -// Check if .env.example was changed, but not environment variable documentation +// Check if .env.example was changed, but not config variable documentation const envChanged = danger.git.modified_files.find((x) => x.includes('.env.example')) || - danger.git.modified_files.find((x) => x.includes('environment.service.ts')); + danger.git.modified_files.find((x) => x.includes('twenty-config.service.ts')); const envDocsChanged = danger.git.modified_files.includes('self-hosting.mdx'); if (envChanged && !envDocsChanged) { const message = - 'Changes were made to the environment variables, but not to the documentation'; + 'Changes were made to the config variables, but not to the documentation'; const idea = 'Please review your changes and check if a change needs to be documented!'; warn(`${message} - ${idea}`);