diff --git a/apps/server/src/api/v2/slack/handler.ts b/apps/server/src/api/v2/slack/handler.ts index be39afb7f..e02606b05 100644 --- a/apps/server/src/api/v2/slack/handler.ts +++ b/apps/server/src/api/v2/slack/handler.ts @@ -1,56 +1,18 @@ import { getUserOrganizationId } from '@buster/database'; +import { + InitiateOAuthSchema, + OAuthCallbackSchema, + SlackError, + SlackErrorCodes, + UpdateIntegrationSchema, +} from '@buster/server-shared/slack'; import { SlackChannelService } from '@buster/slack'; import type { Context } from 'hono'; import { HTTPException } from 'hono/http-exception'; -import { z } from 'zod'; import { getActiveIntegration, updateDefaultChannel } from './services/slack-helpers'; import * as slackHelpers from './services/slack-helpers'; import { type SlackOAuthService, createSlackOAuthService } from './services/slack-oauth-service'; -// Request schemas -const InitiateOAuthSchema = z.object({ - metadata: z - .object({ - returnUrl: z.string().optional(), - source: z.string().optional(), - projectId: z.string().uuid().optional(), - }) - .optional(), -}); - -const OAuthCallbackSchema = z.object({ - code: z.string(), - state: z.string(), -}); - -const UpdateIntegrationSchema = z.object({ - default_channel: z - .object({ - name: z.string().min(1), - id: z.string().min(1), - }) - .optional(), -}); - -// Custom error class -export class SlackError extends Error { - constructor( - message: string, - public statusCode: 500 | 400 | 401 | 403 | 404 | 409 | 429 | 503 = 500, - public code?: string - ) { - super(message); - this.name = 'SlackError'; - } - - toResponse() { - return { - error: this.message, - code: this.code, - }; - } -} - export class SlackHandler { private slackOAuthService: SlackOAuthService | null = null; private _initializationAttempted = false; diff --git a/apps/server/src/api/v2/slack/index.ts b/apps/server/src/api/v2/slack/index.ts index d8648f76a..915589b80 100644 --- a/apps/server/src/api/v2/slack/index.ts +++ b/apps/server/src/api/v2/slack/index.ts @@ -1,7 +1,8 @@ import { Hono } from 'hono'; import { HTTPException } from 'hono/http-exception'; import { requireAuth } from '../../../middleware/auth'; -import { SlackError, slackHandler } from './handler'; +import { slackHandler } from './handler'; +import { SlackError } from '@buster/server-shared/slack'; const app = new Hono() // Public endpoints (no auth required for OAuth flow) diff --git a/packages/server-shared/package.json b/packages/server-shared/package.json index 12432e822..6a867366f 100644 --- a/packages/server-shared/package.json +++ b/packages/server-shared/package.json @@ -34,6 +34,10 @@ "./currency": { "types": "./dist/currency/index.d.ts", "default": "./dist/currency/index.js" + }, + "./slack": { + "types": "./dist/slack/index.d.ts", + "default": "./dist/slack/index.js" } }, "dependencies": { diff --git a/packages/server-shared/src/slack/errors.types.ts b/packages/server-shared/src/slack/errors.types.ts new file mode 100644 index 000000000..c37c89ea4 --- /dev/null +++ b/packages/server-shared/src/slack/errors.types.ts @@ -0,0 +1,37 @@ +// Custom error class for Slack integration errors +export class SlackError extends Error { + constructor( + message: string, + public statusCode: 500 | 400 | 401 | 403 | 404 | 409 | 429 | 503 = 500, + public code?: string + ) { + super(message); + this.name = 'SlackError'; + } + + toResponse() { + return { + error: this.message, + code: this.code, + }; + } +} + +// Common error codes +export const SlackErrorCodes = { + INTEGRATION_NOT_CONFIGURED: 'INTEGRATION_NOT_CONFIGURED', + INTEGRATION_DISABLED: 'INTEGRATION_DISABLED', + INTEGRATION_EXISTS: 'INTEGRATION_EXISTS', + INTEGRATION_NOT_FOUND: 'INTEGRATION_NOT_FOUND', + OAUTH_INIT_ERROR: 'OAUTH_INIT_ERROR', + GET_INTEGRATION_ERROR: 'GET_INTEGRATION_ERROR', + REMOVE_INTEGRATION_ERROR: 'REMOVE_INTEGRATION_ERROR', + UPDATE_DEFAULT_CHANNEL_ERROR: 'UPDATE_DEFAULT_CHANNEL_ERROR', + INVALID_REQUEST_BODY: 'INVALID_REQUEST_BODY', + TOKEN_RETRIEVAL_ERROR: 'TOKEN_RETRIEVAL_ERROR', + INVALID_TOKEN: 'INVALID_TOKEN', + RATE_LIMITED: 'RATE_LIMITED', + GET_CHANNELS_ERROR: 'GET_CHANNELS_ERROR', +} as const; + +export type SlackErrorCode = (typeof SlackErrorCodes)[keyof typeof SlackErrorCodes]; diff --git a/packages/server-shared/src/slack/index.ts b/packages/server-shared/src/slack/index.ts new file mode 100644 index 000000000..7621d93fd --- /dev/null +++ b/packages/server-shared/src/slack/index.ts @@ -0,0 +1,11 @@ +// Export all request types and schemas +export * from './requests.types'; +export type * from './requests.types'; + +// Export all response types +export * from './responses.types'; +export type * from './responses.types'; + +// Export error types and classes +export * from './errors.types'; +export type * from './errors.types';