/** * Copyright 2025 LY Corporation * * LY Corporation licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ import { registerAs } from '@nestjs/config'; import Joi from 'joi'; import { v4 as uuidv4 } from 'uuid'; export const appConfigSchema = Joi.object({ APP_PORT: Joi.number().default(4000), APP_ADDRESS: Joi.string().default('0.0.0.0'), ADMIN_WEB_URL: Joi.string().default('http://localhost:3000'), INITIAL_SUPER_ADMIN_PHONE_NUMBER: Joi.string().allow('').optional(), ADMIN_CANDIDATE_EMAILS: Joi.string().allow('').optional(), ALLOW_OAUTH_EMAIL_LINKING: Joi.boolean().default(false), GITEA_API_URL: Joi.string().uri().default('https://gitea.hmac.kr/api/v1'), GITEA_API_TOKEN: Joi.string().allow('').optional(), GITHUB_API_TOKEN: Joi.string().allow('').optional(), JIRA_API_EMAIL: Joi.string().email().allow('').optional(), JIRA_API_TOKEN: Joi.string().allow('').optional(), JIRA_WEBHOOK_SECRET: Joi.string().allow('').optional(), JIRA_ISSUE_TYPE: Joi.string().default('Task'), BASE_URL: Joi.string().optional(), SUPPORT_API_BASE_URL: Joi.string().uri().default('http://127.0.0.1:8010'), MASTER_API_KEY: Joi.string().allow('').optional(), AUTO_FEEDBACK_DELETION_ENABLED: Joi.boolean().default(false), AUTO_FEEDBACK_DELETION_PERIOD_DAYS: Joi.number().when( 'AUTO_FEEDBACK_DELETION_ENABLED', { is: true, then: Joi.required(), otherwise: Joi.optional(), }, ), ABC_WEBHOOK_ENABLED: Joi.boolean().default(false), ABC_WEBHOOK_PATH: Joi.string().default('/integrations/abc/webhooks'), ABC_WEBHOOK_TOKEN: Joi.string().allow('').optional(), ABC_WEBHOOK_SIGNING_SECRET: Joi.string().allow('').optional(), ABC_WEBHOOK_ALLOWED_PROJECT_IDS: Joi.string().allow('').optional(), ABC_WEBHOOK_CLOCK_SKEW_SECONDS: Joi.number().default(300), ABC_WEBHOOK_MAX_BODY_BYTES: Joi.number().default(262144), NAVER_WORKS_ENABLED: Joi.boolean().default(false), NAVER_WORKS_API_BASE_URL: Joi.string().uri().default('https://www.worksapis.com/v1.0'), NAVER_WORKS_AUTH_URL: Joi.string().uri().default('https://auth.worksmobile.com/oauth2/v2.0/token'), NAVER_WORKS_ACCESS_TOKEN: Joi.string().allow('').optional(), NAVER_WORKS_BOT_ID: Joi.string().allow('').optional(), NAVER_WORKS_DEFAULT_ROOM_ID: Joi.string().allow('').optional(), NAVER_WORKS_CLIENT_ID: Joi.string().allow('').optional(), NAVER_WORKS_CLIENT_SECRET: Joi.string().allow('').optional(), NAVER_WORKS_SERVICE_ACCOUNT: Joi.string().allow('').optional(), NAVER_WORKS_PRIVATE_KEY: Joi.string().allow('').optional(), NAVER_WORKS_SCOPE: Joi.string().default('bot.message bot user.email.read'), NAVER_WORKS_MAX_RETRIES: Joi.number().default(3), NAVER_WORKS_MAX_MESSAGE_LENGTH: Joi.number().default(1000), }); export const appConfig = registerAs('app', () => ({ port: process.env.APP_PORT, address: process.env.APP_ADDRESS, adminWebUrl: process.env.ADMIN_WEB_URL, initialSuperAdminPhoneNumber: process.env.INITIAL_SUPER_ADMIN_PHONE_NUMBER, adminCandidateEmails: process.env.ADMIN_CANDIDATE_EMAILS?.split(',') .map((email) => email.trim().toLowerCase()) .filter((email) => email.length > 0) ?? [], allowOAuthEmailLinking: process.env.ALLOW_OAUTH_EMAIL_LINKING === 'true', baseUrl: process.env.BASE_URL, supportApiBaseUrl: process.env.SUPPORT_API_BASE_URL ?? 'http://127.0.0.1:8010', masterApiKey: process.env.MASTER_API_KEY, giteaApiUrl: process.env.GITEA_API_URL, giteaApiToken: process.env.GITEA_API_TOKEN, githubApiToken: process.env.GITHUB_API_TOKEN, jiraApiEmail: process.env.JIRA_API_EMAIL, jiraApiToken: process.env.JIRA_API_TOKEN, jiraWebhookSecret: process.env.JIRA_WEBHOOK_SECRET, jiraIssueType: process.env.JIRA_ISSUE_TYPE, enableAutoFeedbackDeletion: process.env.AUTO_FEEDBACK_DELETION_ENABLED === 'true', autoFeedbackDeletionPeriodDays: process.env.AUTO_FEEDBACK_DELETION_PERIOD_DAYS, abcWebhookEnabled: process.env.ABC_WEBHOOK_ENABLED === 'true', abcWebhookPath: process.env.ABC_WEBHOOK_PATH, abcWebhookToken: process.env.ABC_WEBHOOK_TOKEN, abcWebhookSigningSecret: process.env.ABC_WEBHOOK_SIGNING_SECRET, abcWebhookAllowedProjectIds: process.env.ABC_WEBHOOK_ALLOWED_PROJECT_IDS, abcWebhookClockSkewSeconds: Number(process.env.ABC_WEBHOOK_CLOCK_SKEW_SECONDS ?? 300), abcWebhookMaxBodyBytes: Number(process.env.ABC_WEBHOOK_MAX_BODY_BYTES ?? 262144), naverWorksEnabled: process.env.NAVER_WORKS_ENABLED === 'true', naverWorksApiBaseUrl: process.env.NAVER_WORKS_API_BASE_URL ?? 'https://www.worksapis.com/v1.0', naverWorksAuthUrl: process.env.NAVER_WORKS_AUTH_URL ?? 'https://auth.worksmobile.com/oauth2/v2.0/token', naverWorksAccessToken: process.env.NAVER_WORKS_ACCESS_TOKEN, naverWorksBotId: process.env.NAVER_WORKS_BOT_ID, naverWorksDefaultRoomId: process.env.NAVER_WORKS_DEFAULT_ROOM_ID, naverWorksClientId: process.env.NAVER_WORKS_CLIENT_ID, naverWorksClientSecret: process.env.NAVER_WORKS_CLIENT_SECRET, naverWorksServiceAccount: process.env.NAVER_WORKS_SERVICE_ACCOUNT, naverWorksPrivateKey: process.env.NAVER_WORKS_PRIVATE_KEY, naverWorksScope: process.env.NAVER_WORKS_SCOPE ?? 'bot.message bot user.email.read', naverWorksMaxRetries: Number(process.env.NAVER_WORKS_MAX_RETRIES ?? 3), naverWorksMaxMessageLength: Number(process.env.NAVER_WORKS_MAX_MESSAGE_LENGTH ?? 1000), serverId: uuidv4(), }));