Skip to content
Draft
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
40 changes: 20 additions & 20 deletions apps/sim/app/api/health/route.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { NextResponse } from 'next/server'

export async function GET() {
try {
return NextResponse.json(
{
status: 'healthy',
timestamp: new Date().toISOString(),
service: 'sim-app',
},
{ status: 200 },
)
} catch (error) {
return NextResponse.json(
{
status: 'unhealthy',
timestamp: new Date().toISOString(),
service: 'sim-app',
error: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 },
)
}
try {
return NextResponse.json(
{
status: 'healthy',
timestamp: new Date().toISOString(),
service: 'sim-app',
},
{ status: 200 }
)
} catch (error) {
return NextResponse.json(
{
status: 'unhealthy',
timestamp: new Date().toISOString(),
service: 'sim-app',
error: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 }
)
}
}
62 changes: 34 additions & 28 deletions apps/sim/app/api/workspaces/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,46 @@ export async function GET() {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

// Get all workspaces where the user has permissions
const userWorkspaces = await db
.select({
workspace: workspace,
permissionType: permissions.permissionType,
})
.from(permissions)
.innerJoin(workspace, eq(permissions.entityId, workspace.id))
.where(and(eq(permissions.userId, session.user.id), eq(permissions.entityType, 'workspace')))
.orderBy(desc(workspace.createdAt))
try {
// Get all workspaces where the user has permissions
const userWorkspaces = await db
.select({
workspace: workspace,
permissionType: permissions.permissionType,
})
.from(permissions)
.innerJoin(workspace, eq(permissions.entityId, workspace.id))
.where(and(eq(permissions.userId, session.user.id), eq(permissions.entityType, 'workspace')))
.orderBy(desc(workspace.createdAt))

if (userWorkspaces.length === 0) {
// Create a default workspace for the user
const defaultWorkspace = await createDefaultWorkspace(session.user.id, session.user.name)
if (userWorkspaces.length === 0) {
// Create a default workspace for the user
const defaultWorkspace = await createDefaultWorkspace(session.user.id, session.user.name)

// Migrate existing workflows to the default workspace
await migrateExistingWorkflows(session.user.id, defaultWorkspace.id)
// Migrate existing workflows to the default workspace
await migrateExistingWorkflows(session.user.id, defaultWorkspace.id)

return NextResponse.json({ workspaces: [defaultWorkspace] })
}
return NextResponse.json({ workspaces: [defaultWorkspace] })
}

// If user has workspaces but might have orphaned workflows, migrate them
await ensureWorkflowsHaveWorkspace(session.user.id, userWorkspaces[0].workspace.id)
// If user has workspaces but might have orphaned workflows, migrate them
await ensureWorkflowsHaveWorkspace(session.user.id, userWorkspaces[0].workspace.id)

// Format the response with permission information
const workspacesWithPermissions = userWorkspaces.map(
({ workspace: workspaceDetails, permissionType }) => ({
...workspaceDetails,
role: permissionType === 'admin' ? 'owner' : 'member', // Map admin to owner for compatibility
permissions: permissionType,
})
)
// Format the response with permission information
const workspacesWithPermissions = userWorkspaces.map(
({ workspace: workspaceDetails, permissionType }) => ({
...workspaceDetails,
role: permissionType === 'admin' ? 'owner' : 'member',
permissions: permissionType,
})
)

return NextResponse.json({ workspaces: workspacesWithPermissions })
return NextResponse.json({ workspaces: workspacesWithPermissions })
} catch (error) {
logger.error('Failed to fetch user workspaces', { error, userId: session.user.id })
// Degrade gracefully to avoid hard-blocking the workspace page
return NextResponse.json({ workspaces: [] })
}
}

// POST /api/workspaces - Create a new workspace
Expand Down
6 changes: 1 addition & 5 deletions apps/sim/app/workspace/[workspaceId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { redirect } from 'next/navigation'

export default function WorkspacePage({
params,
}: {
params: { workspaceId: string }
}) {
export default function WorkspacePage({ params }: { params: { workspaceId: string } }) {
const { workspaceId } = params
redirect(`/workspace/${workspaceId}/w`)
}
11 changes: 10 additions & 1 deletion apps/sim/contexts/socket-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,16 @@ export function SocketProvider({ children, user }: SocketProviderProps) {
// Generate initial token for socket authentication
const token = await generateSocketToken()

const socketUrl = getEnv('NEXT_PUBLIC_SOCKET_URL') || 'http://localhost:3002'
// Only attempt to connect if socket URL is explicitly configured in production.
// In environments without a socket server, skip initialization gracefully.
const configuredSocketUrl = getEnv('NEXT_PUBLIC_SOCKET_URL')
const socketUrl = configuredSocketUrl || 'http://localhost:3002'

if (!configuredSocketUrl && getEnv('NODE_ENV') === 'production') {
logger.warn('Socket server URL is not configured; skipping socket initialization')
setIsConnecting(false)
return
}

logger.info('Attempting to connect to Socket.IO server', {
url: socketUrl,
Expand Down