{"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * Copyright (c) moroo\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { WebClient } from '@slack/web-api';\nimport { IncomingWebhook } from '@slack/webhook';\n\nimport { TimeoutError } from './types.js';\nimport { logger, waitForTimeout } from './utils.js';\n\nimport type {\n  FilesUploadV2Options,\n  FilesUploadV2Response,\n  SlackIncomingWebhookOptions,\n  SlackWebClientOptions,\n} from './types.js';\nimport type {\n  ChatPostMessageArguments,\n  ChatPostMessageResponse,\n  FilesCompleteUploadExternalArguments,\n  FilesCompleteUploadExternalResponse,\n  FilesGetUploadURLExternalArguments,\n  FilesGetUploadURLExternalResponse,\n  FilesInfoArguments,\n  FilesInfoResponse,\n  FilesUploadV2Arguments,\n} from '@slack/web-api';\nimport type {\n  IncomingWebhookResult,\n  IncomingWebhookSendArguments,\n} from '@slack/webhook';\n\n/**\n * A client wrapper for Slack's WebClient API that simplifies common operations.\n *\n * This class provides methods for posting messages, uploading files, and interacting\n * with Slack's API in a more convenient way.\n *\n * @example\n * ```typescript\n * const slackWebClient = new SlackWebClient({\n *   token: 'xoxb-your-token-here'\n * });\n *\n * // Post a message\n * await slackWebClient.postMessage({\n *   channel: 'C12345',\n *   text: 'Hello from WebdriverIO!'\n * });\n *\n * // Upload a file\n * await slackWebClient.upload({\n *   channel_id: 'C12345',\n *   file: '/path/to/report.html',\n *   title: 'Test Report'\n * });\n * ```\n */\nclass SlackWebClient {\n  private _token: string;\n  private _client: WebClient;\n\n  /**\n   * Creates an instance of the Slack Web Client.\n   *\n   * @param {SlackWebClientOptions | undefined} options - The options for configuring the Slack client, excluding 'type' and 'channel'.\n   */\n  constructor(options: SlackWebClientOptions) {\n    const { token, ...rest } = options;\n\n    this._client = new WebClient(token, rest);\n    this._token = token;\n  }\n\n  /**\n   * Gets the authentication token for the Slack API.\n   * @returns The current token value or undefined if not set.\n   */\n  public get token(): string | undefined {\n    return this._token;\n  }\n\n  /**\n   * Gets the Slack WebClient instance.\n   * @returns {WebClient} The Slack WebClient instance used for API interactions.\n   */\n  public get client(): WebClient {\n    return this._client;\n  }\n\n  /**\n   * Posts a message to a Slack channel.\n   *\n   * @param payload - The arguments for posting a message to Slack\n   * @returns A promise that resolves to the chat post message response\n   * @throws Will throw and log an error if the message posting fails\n   */\n  public async postMessage(\n    payload: ChatPostMessageArguments\n  ): Promise<ChatPostMessageResponse> {\n    try {\n      const response = await this._client.chat.postMessage(payload);\n\n      return response;\n    } catch (error) {\n      logger.error(error);\n      throw error;\n    }\n  }\n\n  /**\n   * Uploads files to Slack using the files.uploadV2 API endpoint.\n   *\n   * @param payload - The file upload parameters conforming to FilesUploadV2Arguments\n   * @param options - Optional configuration for the upload process\n   * @param options.waitForUpload - Whether to wait for file processing completion (default: true)\n   * @param options.timeout - Maximum time in milliseconds to wait for upload completion (default: 30000)\n   * @param options.interval - Polling interval in milliseconds when checking upload status (default: 1000)\n   *\n   * @returns Promise resolving to the Slack API response (FilesUploadV2Response)\n   *\n   * @throws Will throw and log any errors encountered during the upload process\n   *\n   * @example\n   * const result = await slackClient.uploadV2({\n   *   channel_id: \"C12345\",\n   *   file: someFileBuffer,\n   *   filename: \"report.pdf\",\n   *   token: \"xoxb-token\"\n   * });\n   */\n  public async uploadV2(\n    payload: FilesUploadV2Arguments,\n    options?: FilesUploadV2Options\n  ): Promise<FilesUploadV2Response> {\n    const {\n      waitForUpload = true,\n      timeout = 30000,\n      interval = 1000,\n    } = options ?? {};\n    // Slack 파일 업로드 API 호출\n    try {\n      const response = await this._client.filesUploadV2(payload);\n\n      // 업로드가 성공적이면\n      if (waitForUpload && response.ok) {\n        const files = response.files?.flatMap((file) => file.files) ?? [];\n\n        // 각 파일에 대해 업로드 완료까지 대기\n        for await (const file of files) {\n          try {\n            if (file?.id) {\n              await this.waitForUpload(\n                file.id,\n                payload.token,\n                timeout,\n                interval\n              );\n            }\n          } catch (error) {\n            logger.error(error);\n          }\n        }\n      }\n\n      // 최종 업로드 응답 반환\n      return response;\n    } catch (error) {\n      logger.error(error);\n      throw error; // 업로드 실패 시 에러 반환\n    }\n  }\n\n  /**\n   * Waits for a file to be processed and uploaded on Slack.\n   * This method repeatedly checks the file info until the file's mimetype is available,\n   * indicating that the file has been successfully processed.\n   *\n   * @param fileId - The ID of the file to check\n   * @param timeout - Maximum time in milliseconds to wait for the file upload (default: 30000)\n   * @param interval - Time in milliseconds between each check (default: 1000)\n   * @returns A Promise that resolves to the FilesInfoResponse once the file is processed\n   * @throws {TimeoutError} If the file is not processed within the specified timeout\n   * @throws {Error} If any error occurs during the file info retrieval\n   */\n  public async waitForUpload(\n    fileId: string,\n    token?: string,\n    timeout: number = 30000,\n    interval: number = 1000\n  ): Promise<FilesInfoResponse> {\n    const startTime = Date.now();\n\n    while (Date.now() - startTime < timeout) {\n      try {\n        const response = await this.filesInfo({\n          token: token ?? this._token,\n          file: fileId,\n        });\n\n        if (response?.file?.mimetype) {\n          return response;\n        }\n      } catch (error) {\n        logger.error(error);\n        throw error;\n      }\n\n      await waitForTimeout(interval);\n    }\n\n    throw new TimeoutError(\n      `Timeout: No file info(mimetype) found within ${timeout / 1000} seconds`\n    );\n  }\n\n  /**\n   * Retrieves information about a file.\n   *\n   * @param options - Arguments for retrieving file information\n   * @returns A promise that resolves to the file information response\n   *\n   * @example\n   * ```typescript\n   * const fileInfo = await client.filesInfo({\n   *   file: \"F123456789\"\n   * });\n   * ```\n   */\n  public async filesInfo(\n    options: FilesInfoArguments\n  ): Promise<FilesInfoResponse> {\n    try {\n      const response = await this._client.files.info(options);\n\n      return response;\n    } catch (error) {\n      logger.error(error);\n      throw error;\n    }\n  }\n\n  /**\n   * Retrieves an external upload URL for files.\n   *\n   * @param options - The arguments for the external upload URL request\n   * @returns A promise that resolves to a FilesGetUploadURLExternalResponse\n   * @throws Will throw and log any errors that occur during the request\n   */\n  public async getUploadURLExternal(\n    options: FilesGetUploadURLExternalArguments\n  ): Promise<FilesGetUploadURLExternalResponse> {\n    try {\n      const response = await this._client.files.getUploadURLExternal(options);\n\n      return response;\n    } catch (error) {\n      logger.error(error);\n      throw error;\n    }\n  }\n\n  /**\n   * Completes an external file upload process.\n   * Calls the Slack API's files.completeUploadExternal method.\n   *\n   * @param options - Arguments required for completing an external upload\n   * @returns A promise resolving to the response from the Slack API\n   * @throws Will throw and log any errors that occur during the API call\n   */\n  public async completeUploadExternal(\n    options: FilesCompleteUploadExternalArguments\n  ): Promise<FilesCompleteUploadExternalResponse> {\n    try {\n      const response = await this._client.files.completeUploadExternal(options);\n\n      return response;\n    } catch (error) {\n      logger.error(error);\n      throw error;\n    }\n  }\n}\n\n/**\n * A class that provides an interface for sending messages to Slack via webhooks.\n *\n * This class wraps the Slack IncomingWebhook functionality and provides a simplified\n * interface for sending messages to a Slack channel.\n *\n * @example\n * ```typescript\n * const slackWebhookClient = new SlackWebhookClient({\n *   webhook: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX',\n *   username: 'WebdriverIO Reporter'\n * });\n *\n * await slackWebhookClient.send('Test message');\n * ```\n */\nclass SlackWebhookClient {\n  private _url: string;\n  private _webhook: IncomingWebhook;\n\n  /**\n   * Creates an instance of the Slack IncomingWebhook.\n   * @param {SlackIncomingWebhookOptions} options - Configuration options for the Slack webhook.\n   */\n  constructor(options: SlackIncomingWebhookOptions) {\n    const { webhook: url, ...rest } = options;\n\n    this._url = url;\n    this._webhook = new IncomingWebhook(url, rest);\n  }\n\n  /**\n   * Gets the URL for the Slack webhook.\n   * @returns The URL string for the Slack webhook.\n   */\n  public get url(): string {\n    return this._url;\n  }\n\n  /**\n   * Gets the Slack IncomingWebhook instance.\n   *\n   * @returns {IncomingWebhook} The configured Slack webhook client\n   */\n  public get webhook(): IncomingWebhook {\n    return this._webhook;\n  }\n\n  /**\n   * Sends a payload to Slack via webhook.\n   *\n   * @param payload - The content to send to Slack. Can be either a string or an IncomingWebhookSendArguments object.\n   * @returns A Promise that resolves with the IncomingWebhookResult from Slack.\n   * @throws Will re-throw any error that occurs during the send operation after logging it.\n   */\n  public async send(\n    payload: string | IncomingWebhookSendArguments\n  ): Promise<IncomingWebhookResult> {\n    try {\n      const response = await this._webhook.send(payload);\n\n      return response;\n    } catch (error) {\n      logger.error(error);\n      throw error;\n    }\n  }\n}\n\nexport { SlackWebClient, SlackWebhookClient };\n"],"mappings":"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","names":[]}