Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
473 changes: 472 additions & 1 deletion apps/docs/openapi.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions apps/realtime/src/database/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ const socketDb = drizzle(
instrumentPoolClient(
postgres(connectionString, {
prepare: false,
// See `packages/db/db.ts` — skips the per-connection pg_type roundtrip.
fetch_types: false,
idle_timeout: 10,
connect_timeout: 20,
max: 10,
Expand Down
2 changes: 2 additions & 0 deletions apps/sim/app/api/v1/audit-logs/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const {
vi.mock('@/app/api/v1/middleware', () => ({
checkRateLimit: mockCheckRateLimit,
createRateLimitResponse: vi.fn(),
v1ValidationErrorResponse: (e: { issues: unknown[] }) =>
NextResponse.json({ error: 'Validation error', details: e.issues }, { status: 400 }),
}))

vi.mock('@/app/api/v1/audit-logs/auth', () => ({
Expand Down
17 changes: 7 additions & 10 deletions apps/sim/app/api/v1/audit-logs/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { getErrorMessage } from '@sim/utils/errors'
import { generateId } from '@sim/utils/id'
import { type NextRequest, NextResponse } from 'next/server'
import { v1ListAuditLogsContract } from '@/lib/api/contracts/v1/audit-logs'
import { getValidationErrorMessage, parseRequest } from '@/lib/api/server'
import { parseRequest } from '@/lib/api/server'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { validateEnterpriseAuditAccess } from '@/app/api/v1/audit-logs/auth'
import { formatAuditLogEntry } from '@/app/api/v1/audit-logs/format'
Expand All @@ -35,7 +35,11 @@ import {
queryAuditLogs,
} from '@/app/api/v1/audit-logs/query'
import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta'
import { checkRateLimit, createRateLimitResponse } from '@/app/api/v1/middleware'
import {
checkRateLimit,
createRateLimitResponse,
v1ValidationErrorResponse,
} from '@/app/api/v1/middleware'

const logger = createLogger('V1AuditLogsAPI')

Expand Down Expand Up @@ -65,14 +69,7 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
request,
{},
{
validationErrorResponse: (error) =>
NextResponse.json(
{
error: getValidationErrorMessage(error, 'Invalid parameters'),
details: error.issues,
},
{ status: 400 }
),
validationErrorResponse: (error) => v1ValidationErrorResponse(error, 'Invalid parameters'),
}
)
if (!parsed.success) return parsed.response
Expand Down
2 changes: 2 additions & 0 deletions apps/sim/app/api/v1/files/[fileId]/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ vi.mock('@/app/api/v1/middleware', () => ({
checkRateLimit: mockCheckRateLimit,
createRateLimitResponse: () => new Response('rate limited', { status: 429 }),
validateWorkspaceAccess: mockValidateWorkspaceAccess,
v1ValidationErrorResponse: (e: { issues: unknown[] }) =>
NextResponse.json({ error: 'Validation error', details: e.issues }, { status: 400 }),
}))
vi.mock('@/lib/uploads/contexts/workspace', () => ({
getWorkspaceFile: mockGetWorkspaceFile,
Expand Down
9 changes: 7 additions & 2 deletions apps/sim/app/api/v1/files/[fileId]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { performDeleteWorkspaceFileItems } from '@/lib/workspace-files/orchestra
import {
checkRateLimit,
createRateLimitResponse,
v1ValidationErrorResponse,
validateWorkspaceAccess,
} from '@/app/api/v1/middleware'

Expand All @@ -38,7 +39,9 @@ export const GET = withRouteHandler(async (request: NextRequest, context: FileRo
}

const userId = rateLimit.userId!
const parsed = await parseRequest(v1DownloadFileContract, request, context)
const parsed = await parseRequest(v1DownloadFileContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response

const { fileId } = parsed.data.params
Expand Down Expand Up @@ -119,7 +122,9 @@ export const DELETE = withRouteHandler(async (request: NextRequest, context: Fil
}

const userId = rateLimit.userId!
const parsed = await parseRequest(v1DeleteFileContract, request, context)
const parsed = await parseRequest(v1DeleteFileContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response

const { fileId } = parsed.data.params
Expand Down
10 changes: 9 additions & 1 deletion apps/sim/app/api/v1/files/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
checkRateLimit,
checkWorkspaceScope,
createRateLimitResponse,
v1ValidationErrorResponse,
validateWorkspaceAccess,
} from '@/app/api/v1/middleware'

Expand All @@ -43,7 +44,14 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
}

const userId = rateLimit.userId!
const parsed = await parseRequest(v1ListFilesContract, request, {})
const parsed = await parseRequest(
v1ListFilesContract,
request,
{},
{
validationErrorResponse: v1ValidationErrorResponse,
}
)
if (!parsed.success) return parsed.response

const { workspaceId } = parsed.data.query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { parseRequest } from '@/lib/api/server'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { deleteDocument } from '@/lib/knowledge/documents/service'
import { handleError, resolveKnowledgeBase, serializeDate } from '@/app/api/v1/knowledge/utils'
import { authenticateRequest } from '@/app/api/v1/middleware'
import { authenticateRequest, v1ValidationErrorResponse } from '@/app/api/v1/middleware'

export const dynamic = 'force-dynamic'
export const revalidate = 0
Expand All @@ -28,7 +28,9 @@ export const GET = withRouteHandler(
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1GetKnowledgeDocumentContract, request, context)
const parsed = await parseRequest(v1GetKnowledgeDocumentContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response
const { id: knowledgeBaseId, documentId } = parsed.data.params

Expand Down Expand Up @@ -117,7 +119,9 @@ export const DELETE = withRouteHandler(
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1DeleteKnowledgeDocumentContract, request, context)
const parsed = await parseRequest(v1DeleteKnowledgeDocumentContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response
const { id: knowledgeBaseId, documentId } = parsed.data.params

Expand Down
2 changes: 2 additions & 0 deletions apps/sim/app/api/v1/knowledge/[id]/documents/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const SYSTEM_BILLING_ATTRIBUTION = {

vi.mock('@/app/api/v1/middleware', () => ({
authenticateRequest: mockAuthenticateRequest,
v1ValidationErrorResponse: (e: { issues: unknown[] }) =>
NextResponse.json({ error: 'Validation error', details: e.issues }, { status: 400 }),
}))

vi.mock('@/app/api/v1/knowledge/utils', () => ({
Expand Down
10 changes: 7 additions & 3 deletions apps/sim/app/api/v1/knowledge/[id]/documents/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import type { DocumentSortField, SortOrder } from '@/lib/knowledge/documents/typ
import { uploadWorkspaceFile } from '@/lib/uploads/contexts/workspace'
import { validateFileType } from '@/lib/uploads/utils/validation'
import { handleError, resolveKnowledgeBase, serializeDate } from '@/app/api/v1/knowledge/utils'
import { authenticateRequest } from '@/app/api/v1/middleware'
import { authenticateRequest, v1ValidationErrorResponse } from '@/app/api/v1/middleware'

export const dynamic = 'force-dynamic'
export const revalidate = 0
Expand All @@ -44,7 +44,9 @@ export const GET = withRouteHandler(async (request: NextRequest, context: Docume
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1ListKnowledgeDocumentsContract, request, context)
const parsed = await parseRequest(v1ListKnowledgeDocumentsContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response

const { workspaceId, limit, offset, search, enabledFilter, sortBy, sortOrder } =
Expand Down Expand Up @@ -99,7 +101,9 @@ export const POST = withRouteHandler(
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1UploadKnowledgeDocumentContract, request, context)
const parsed = await parseRequest(v1UploadKnowledgeDocumentContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response
const { id: knowledgeBaseId } = parsed.data.params

Expand Down
14 changes: 10 additions & 4 deletions apps/sim/app/api/v1/knowledge/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
handleError,
resolveKnowledgeBase,
} from '@/app/api/v1/knowledge/utils'
import { authenticateRequest } from '@/app/api/v1/middleware'
import { authenticateRequest, v1ValidationErrorResponse } from '@/app/api/v1/middleware'

export const dynamic = 'force-dynamic'
export const revalidate = 0
Expand All @@ -29,7 +29,9 @@ export const GET = withRouteHandler(async (request: NextRequest, context: Knowle
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1GetKnowledgeBaseContract, request, context)
const parsed = await parseRequest(v1GetKnowledgeBaseContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response

const { id } = parsed.data.params
Expand All @@ -54,7 +56,9 @@ export const PUT = withRouteHandler(async (request: NextRequest, context: Knowle
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1UpdateKnowledgeBaseContract, request, context)
const parsed = await parseRequest(v1UpdateKnowledgeBaseContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response

const { id } = parsed.data.params
Expand Down Expand Up @@ -106,7 +110,9 @@ export const DELETE = withRouteHandler(
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1DeleteKnowledgeBaseContract, request, context)
const parsed = await parseRequest(v1DeleteKnowledgeBaseContract, request, context, {
validationErrorResponse: v1ValidationErrorResponse,
})
if (!parsed.success) return parsed.response

const { id } = parsed.data.params
Expand Down
24 changes: 21 additions & 3 deletions apps/sim/app/api/v1/knowledge/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { EMBEDDING_DIMENSIONS, getConfiguredEmbeddingModel } from '@/lib/knowledge/embeddings'
import { createKnowledgeBase, getKnowledgeBases } from '@/lib/knowledge/service'
import { formatKnowledgeBase, handleError } from '@/app/api/v1/knowledge/utils'
import { authenticateRequest, validateWorkspaceAccess } from '@/app/api/v1/middleware'
import {
authenticateRequest,
v1ValidationErrorResponse,
validateWorkspaceAccess,
} from '@/app/api/v1/middleware'

export const dynamic = 'force-dynamic'
export const revalidate = 0
Expand All @@ -21,7 +25,14 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1ListKnowledgeBasesContract, request, {})
const parsed = await parseRequest(
v1ListKnowledgeBasesContract,
request,
{},
{
validationErrorResponse: v1ValidationErrorResponse,
}
)
if (!parsed.success) return parsed.response

const { workspaceId } = parsed.data.query
Expand Down Expand Up @@ -50,7 +61,14 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1CreateKnowledgeBaseContract, request, {})
const parsed = await parseRequest(
v1CreateKnowledgeBaseContract,
request,
{},
{
validationErrorResponse: v1ValidationErrorResponse,
}
)
if (!parsed.success) return parsed.response

const { workspaceId, name, description, chunkingConfig } = parsed.data.body
Expand Down
2 changes: 2 additions & 0 deletions apps/sim/app/api/v1/knowledge/search/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ vi.mock('@/lib/knowledge/embeddings', () => ({
vi.mock('@/app/api/v1/middleware', () => ({
authenticateRequest: mockAuthenticateRequest,
validateWorkspaceAccess: mockValidateWorkspaceAccess,
v1ValidationErrorResponse: (e: { issues: unknown[] }) =>
NextResponse.json({ error: 'Validation error', details: e.issues }, { status: 400 }),
}))

vi.mock('@/app/api/v1/knowledge/utils', () => ({
Expand Down
15 changes: 13 additions & 2 deletions apps/sim/app/api/v1/knowledge/search/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ import {
} from '@/app/api/knowledge/search/utils'
import { checkKnowledgeBaseAccess, type KnowledgeBaseAccessResult } from '@/app/api/knowledge/utils'
import { handleError } from '@/app/api/v1/knowledge/utils'
import { authenticateRequest, validateWorkspaceAccess } from '@/app/api/v1/middleware'
import {
authenticateRequest,
v1ValidationErrorResponse,
validateWorkspaceAccess,
} from '@/app/api/v1/middleware'

export const dynamic = 'force-dynamic'
export const revalidate = 0
Expand All @@ -35,7 +39,14 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
const { requestId, userId, rateLimit } = auth

try {
const parsed = await parseRequest(v1KnowledgeSearchContract, request, {})
const parsed = await parseRequest(
v1KnowledgeSearchContract,
request,
{},
{
validationErrorResponse: v1ValidationErrorResponse,
}
)
if (!parsed.success) return parsed.response

const { workspaceId, topK, query, tagFilters } = parsed.data.body
Expand Down
5 changes: 2 additions & 3 deletions apps/sim/app/api/v1/logs/meta.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { buildRateLimitHeaders } from '@/lib/api/server/rate-limit-context'
import { checkServerSideUsageLimits } from '@/lib/billing'
import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription'
import { getEffectiveCurrentPeriodCost } from '@/lib/billing/core/usage'
Expand Down Expand Up @@ -74,9 +75,7 @@ export function createApiResponse<T>(
limits,
},
headers: {
'X-RateLimit-Limit': apiRateLimit.limit.toString(),
'X-RateLimit-Remaining': apiRateLimit.remaining.toString(),
'X-RateLimit-Reset': apiRateLimit.resetAt.toISOString(),
...buildRateLimitHeaders(apiRateLimit),
},
}
}
12 changes: 3 additions & 9 deletions apps/sim/app/api/v1/logs/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { generateId } from '@sim/utils/id'
import { eq, sql } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { v1ListLogsContract } from '@/lib/api/contracts/v1/logs'
import { getValidationErrorMessage, parseRequest } from '@/lib/api/server'
import { parseRequest } from '@/lib/api/server'
import { MATERIALIZE_CONCURRENCY, mapWithConcurrency } from '@/lib/core/utils/concurrency'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { materializeExecutionData } from '@/lib/logs/execution/trace-store'
Expand All @@ -14,6 +14,7 @@ import { createApiResponse, getUserLimits } from '@/app/api/v1/logs/meta'
import {
checkRateLimit,
createRateLimitResponse,
v1ValidationErrorResponse,
validateWorkspaceAccess,
} from '@/app/api/v1/middleware'

Expand Down Expand Up @@ -54,14 +55,7 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
request,
{},
{
validationErrorResponse: (error) =>
NextResponse.json(
{
error: getValidationErrorMessage(error, 'Invalid parameters'),
details: error.issues,
},
{ status: 400 }
),
validationErrorResponse: (error) => v1ValidationErrorResponse(error, 'Invalid parameters'),
}
)
if (!parsed.success) return parsed.response
Expand Down
Loading
Loading