Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions apps/sim/app/api/tools/monday/boards/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { NextResponse } from 'next/server'
import { createLogger } from '@sim/logger'
import { generateRequestId } from '@/lib/core/utils/request'
import { executeMondayQuery, QUERIES } from '@/tools/monday/graphql'

export const dynamic = 'force-dynamic'

const logger = createLogger('MondayBoardsAPI')

interface MondayBoard {
id: string
name: string
description?: string
board_kind: string
state: string
}

export async function POST(request: Request) {
try {
const requestId = generateRequestId()
const body = await request.json()
const { apiKey } = body

if (!apiKey) {
logger.error('Missing API key in request')
return NextResponse.json({ error: 'API key is required' }, { status: 400 })
}

logger.info('Fetching Monday.com boards', { requestId })

const data = await executeMondayQuery<{ boards: MondayBoard[] }>(apiKey, {
query: QUERIES.GET_BOARDS,
})

const boards = (data.boards || [])
.filter((board) => board.state === 'active')
.map((board) => ({
id: board.id,
name: board.name,
description: board.description,
kind: board.board_kind,
}))

logger.info(`Successfully fetched ${boards.length} Monday.com boards`, { requestId })
return NextResponse.json({ items: boards })
} catch (error) {
logger.error('Error fetching Monday.com boards:', error)
return NextResponse.json(
{ error: 'Failed to retrieve Monday.com boards', details: (error as Error).message },
{ status: 500 }
)
}
}
59 changes: 59 additions & 0 deletions apps/sim/app/api/tools/monday/columns/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { NextResponse } from 'next/server'
import { createLogger } from '@sim/logger'
import { generateRequestId } from '@/lib/core/utils/request'
import { executeMondayQuery, QUERIES } from '@/tools/monday/graphql'

export const dynamic = 'force-dynamic'

const logger = createLogger('MondayColumnsAPI')

interface MondayColumn {
id: string
title: string
type: string
settings_str?: string
}

export async function POST(request: Request) {
try {
const requestId = generateRequestId()
const body = await request.json()
const { apiKey, boardId } = body

if (!apiKey) {
logger.error('Missing API key in request')
return NextResponse.json({ error: 'API key is required' }, { status: 400 })
}

if (!boardId) {
logger.error('Missing board ID in request')
return NextResponse.json({ error: 'Board ID is required' }, { status: 400 })
}

logger.info('Fetching Monday.com columns', { requestId, boardId })

const data = await executeMondayQuery<{ boards: Array<{ columns: MondayColumn[] }> }>(
apiKey,
{
query: QUERIES.GET_BOARD_COLUMNS,
variables: { boardId: [parseInt(boardId, 10)] },
}
)

const columns = data.boards?.[0]?.columns || []
const formattedColumns = columns.map((col) => ({
id: col.id,
name: col.title,
type: col.type,
}))

logger.info(`Successfully fetched ${formattedColumns.length} columns`, { requestId })
return NextResponse.json({ items: formattedColumns })
} catch (error) {
logger.error('Error fetching Monday.com columns:', error)
return NextResponse.json(
{ error: 'Failed to retrieve columns', details: (error as Error).message },
{ status: 500 }
)
}
}
55 changes: 55 additions & 0 deletions apps/sim/app/api/tools/monday/groups/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { NextResponse } from 'next/server'
import { createLogger } from '@sim/logger'
import { generateRequestId } from '@/lib/core/utils/request'
import { executeMondayQuery, QUERIES } from '@/tools/monday/graphql'

export const dynamic = 'force-dynamic'

const logger = createLogger('MondayGroupsAPI')

interface MondayGroup {
id: string
title: string
color: string
}

export async function POST(request: Request) {
try {
const requestId = generateRequestId()
const body = await request.json()
const { apiKey, boardId } = body

if (!apiKey || !boardId) {
return NextResponse.json(
{ error: 'API key and board ID are required' },
{ status: 400 }
)
}

logger.info('Fetching Monday.com groups', { requestId, boardId })

const data = await executeMondayQuery<{ boards: Array<{ groups: MondayGroup[] }> }>(
apiKey,
{
query: QUERIES.GET_BOARD_GROUPS,
variables: { boardId: [parseInt(boardId, 10)] },
}
)

const groups = data.boards?.[0]?.groups || []
const formattedGroups = groups.map((group) => ({
id: group.id,
name: group.title,
color: group.color,
}))

logger.info(`Successfully fetched ${formattedGroups.length} groups`, { requestId })
return NextResponse.json({ items: formattedGroups })
} catch (error) {
logger.error('Error fetching Monday.com groups:', error)
return NextResponse.json(
{ error: 'Failed to retrieve groups', details: (error as Error).message },
{ status: 500 }
)
}
}
80 changes: 80 additions & 0 deletions apps/sim/app/api/tools/monday/items/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { createLogger } from '@sim/logger'
import { NextResponse } from 'next/server'
import { QUERIES } from '@/tools/monday/graphql'

const logger = createLogger('MondayItemsAPI')

/**
* POST /api/tools/monday/items
* Fetches items from a Monday.com board for selector dropdown
*/
export async function POST(request: Request) {
try {
const body = await request.json()
const { apiKey, boardId } = body

if (!apiKey) {
logger.warn('Missing apiKey in request')
return NextResponse.json({ error: 'API key is required' }, { status: 400 })
}

if (!boardId) {
logger.warn('Missing boardId in request')
return NextResponse.json({ error: 'Board ID is required' }, { status: 400 })
}

logger.info('Fetching Monday.com items', { boardId })

const response = await fetch('https://api.monday.com/v2', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: apiKey,
'API-Version': '2024-01',
},
body: JSON.stringify({
query: QUERIES.GET_BOARD_ITEMS,
variables: {
boardId: [parseInt(boardId, 10)],
limit: 100,
},
}),
})

if (!response.ok) {
const errorText = await response.text()
logger.error('Monday.com API error', {
status: response.status,
error: errorText,
})
return NextResponse.json(
{ error: `Monday.com API error: ${response.status}` },
{ status: response.status }
)
}

const result = await response.json()

if (result.errors) {
logger.error('Monday.com GraphQL errors', { errors: result.errors })
return NextResponse.json(
{ error: 'Failed to fetch items', details: result.errors },
{ status: 400 }
)
}

const items = result.data?.boards?.[0]?.items_page?.items || []

logger.info('Successfully fetched Monday.com items', { count: items.length })

return NextResponse.json({
items: items.map((item: any) => ({
id: item.id,
name: item.name,
})),
})
} catch (error) {
logger.error('Unexpected error fetching Monday.com items', { error })
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}
97 changes: 97 additions & 0 deletions apps/sim/app/api/tools/monday/status-options/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { NextResponse } from 'next/server'
import { createLogger } from '@sim/logger'
import { generateRequestId } from '@/lib/core/utils/request'
import { executeMondayQuery, QUERIES } from '@/tools/monday/graphql'

export const dynamic = 'force-dynamic'

const logger = createLogger('MondayStatusOptionsAPI')

interface MondayColumn {
id: string
title: string
type: string
settings_str?: string
}

interface StatusLabel {
id: string
label: string
color: string
}

export async function POST(request: Request) {
try {
const requestId = generateRequestId()
const body = await request.json()
const { apiKey, boardId, columnId } = body

if (!apiKey || !boardId || !columnId) {
return NextResponse.json(
{ error: 'API key, board ID, and column ID are required' },
{ status: 400 }
)
}

logger.info('Fetching Monday.com status options', { requestId, boardId, columnId })

const data = await executeMondayQuery<{ boards: Array<{ columns: MondayColumn[] }> }>(
apiKey,
{
query: QUERIES.GET_COLUMN_SETTINGS,
variables: {
boardId: [parseInt(boardId, 10)],
columnId,
},
}
)

const column = data.boards?.[0]?.columns?.[0]

if (!column) {
return NextResponse.json({ error: 'Column not found' }, { status: 404 })
}

if (column.type !== 'status' && column.type !== 'color') {
return NextResponse.json(
{ error: `Column type ${column.type} does not have status options` },
{ status: 400 }
)
}

let statusOptions: StatusLabel[] = []

if (column.settings_str) {
try {
const settings = JSON.parse(column.settings_str)
const labels = settings.labels || {}

statusOptions = Object.entries(labels).map(([id, label]: [string, any]) => ({
id,
label: label.label || label,
color: label.color || '#000000',
}))
} catch (parseError) {
logger.error('Failed to parse column settings', {
error: parseError,
settings_str: column.settings_str,
})
}
}

logger.info(`Successfully fetched ${statusOptions.length} status options`, { requestId })
return NextResponse.json({
items: statusOptions.map((option) => ({
id: option.id,
name: option.label,
color: option.color,
})),
})
} catch (error) {
logger.error('Error fetching Monday.com status options:', error)
return NextResponse.json(
{ error: 'Failed to retrieve status options', details: (error as Error).message },
{ status: 500 }
)
}
}
Loading