mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
fix(permissions): make permissions check case insensitive, resolve hydration issues by consolidating environment checking function (#678)
* fix(permissions): make permissions check case insensitive * consolidated use of helpers to fetch environment * use import aliases * fix(voice): added voice functionality back to chat client (#676) * fix(voice): added voice functioanlity back to chat clinet * add logic to support deployed chat in staging * fix(api-timeout): increase timeout for API block to 2 min (#677) * feat(wealthbox): added wealthbox crm (#669) * feat: wealthbox * feat: added tools * feat: tested and finished tools * feat: tested and finished tools * feat: added refresh token * fix: added docs * bun lint * feat: removed files #669 * fix: greptile comments * fix: stringified messages #669 * add visibilty to params --------- Co-authored-by: Adam Gough <adamgough@Adams-MacBook-Pro.local> Co-authored-by: Adam Gough <adamgough@Mac.attlocal.net> Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai> --------- Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Adam Gough <77861281+aadamgough@users.noreply.github.com> Co-authored-by: Adam Gough <adamgough@Adams-MacBook-Pro.local> Co-authored-by: Adam Gough <adamgough@Mac.attlocal.net> Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
This commit is contained in:
@@ -2,7 +2,7 @@ import { and, eq } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { env } from '@/lib/env'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { getBaseDomain } from '@/lib/urls/utils'
|
||||
import { encryptSecret } from '@/lib/utils'
|
||||
@@ -71,9 +71,7 @@ export async function GET(_request: NextRequest, { params }: { params: Promise<{
|
||||
// Create a new result object without the password
|
||||
const { password, ...safeData } = chatInstance[0]
|
||||
|
||||
const isDevelopment = env.NODE_ENV === 'development'
|
||||
|
||||
const chatUrl = isDevelopment
|
||||
const chatUrl = isDev
|
||||
? `http://${chatInstance[0].subdomain}.${getBaseDomain()}`
|
||||
: `https://${chatInstance[0].subdomain}.simstudio.ai`
|
||||
|
||||
@@ -221,9 +219,7 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
|
||||
|
||||
const updatedSubdomain = subdomain || existingChat[0].subdomain
|
||||
|
||||
const isDevelopment = env.NODE_ENV === 'development'
|
||||
|
||||
const chatUrl = isDevelopment
|
||||
const chatUrl = isDev
|
||||
? `http://${updatedSubdomain}.${getBaseDomain()}`
|
||||
: `https://${updatedSubdomain}.simstudio.ai`
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { v4 as uuidv4 } from 'uuid'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { env } from '@/lib/env'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { encryptSecret } from '@/lib/utils'
|
||||
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
|
||||
@@ -169,11 +170,10 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
// Return successful response with chat URL
|
||||
// Check if we're in development or production
|
||||
const isDevelopment = env.NODE_ENV === 'development'
|
||||
const baseUrl = env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'
|
||||
|
||||
let chatUrl: string
|
||||
if (isDevelopment) {
|
||||
if (isDev) {
|
||||
try {
|
||||
const url = new URL(baseUrl)
|
||||
chatUrl = `${url.protocol}//${subdomain}.${url.host}`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { env } from '@/lib/env'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { EnhancedLoggingSession } from '@/lib/logs/enhanced-logging-session'
|
||||
import { buildTraceSpans } from '@/lib/logs/trace-spans'
|
||||
@@ -20,7 +20,6 @@ declare global {
|
||||
}
|
||||
|
||||
const logger = createLogger('ChatAuthUtils')
|
||||
const isDevelopment = env.NODE_ENV === 'development'
|
||||
|
||||
export const encryptAuthToken = (subdomainId: string, type: string): string => {
|
||||
return Buffer.from(`${subdomainId}:${type}:${Date.now()}`).toString('base64')
|
||||
@@ -63,11 +62,11 @@ export const setChatAuthCookie = (
|
||||
name: `chat_auth_${subdomainId}`,
|
||||
value: token,
|
||||
httpOnly: true,
|
||||
secure: !isDevelopment,
|
||||
secure: !isDev,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
// Using subdomain for the domain in production
|
||||
domain: isDevelopment ? undefined : '.simstudio.ai',
|
||||
domain: isDev ? undefined : '.simstudio.ai',
|
||||
maxAge: 60 * 60 * 24, // 24 hours
|
||||
})
|
||||
}
|
||||
@@ -78,7 +77,7 @@ export function addCorsHeaders(response: NextResponse, request: NextRequest) {
|
||||
const origin = request.headers.get('origin') || ''
|
||||
|
||||
// In development, allow any localhost subdomain
|
||||
if (isDevelopment && origin.includes('localhost')) {
|
||||
if (isDev && origin.includes('localhost')) {
|
||||
response.headers.set('Access-Control-Allow-Origin', origin)
|
||||
response.headers.set('Access-Control-Allow-Credentials', 'true')
|
||||
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
isBlobPath,
|
||||
isCloudPath,
|
||||
isS3Path,
|
||||
} from '../utils'
|
||||
} from '@/app/api/files/utils'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@ async function handleCsvBuffer(
|
||||
logger.info(`Parsing CSV in memory: ${filename}`)
|
||||
|
||||
// Use the parseBuffer function from our library
|
||||
const { parseBuffer } = await import('../../../../lib/file-parsers')
|
||||
const { parseBuffer } = await import('@/lib/file-parsers')
|
||||
const result = await parseBuffer(fileBuffer, 'csv')
|
||||
|
||||
return {
|
||||
@@ -492,7 +492,7 @@ async function handleGenericTextBuffer(
|
||||
|
||||
// Try to use a specialized parser if available
|
||||
try {
|
||||
const { parseBuffer, isSupportedFileType } = await import('../../../../lib/file-parsers')
|
||||
const { parseBuffer, isSupportedFileType } = await import('@/lib/file-parsers')
|
||||
|
||||
if (isSupportedFileType(extension)) {
|
||||
const result = await parseBuffer(fileBuffer, extension)
|
||||
@@ -578,7 +578,7 @@ async function parseBufferAsPdf(buffer: Buffer) {
|
||||
// Import parsers dynamically to avoid initialization issues in tests
|
||||
// First try to use the main PDF parser
|
||||
try {
|
||||
const { PdfParser } = await import('../../../../lib/file-parsers/pdf-parser')
|
||||
const { PdfParser } = await import('@/lib/file-parsers/pdf-parser')
|
||||
const parser = new PdfParser()
|
||||
logger.info('Using main PDF parser for buffer')
|
||||
|
||||
@@ -589,7 +589,7 @@ async function parseBufferAsPdf(buffer: Buffer) {
|
||||
} catch (error) {
|
||||
// Fallback to raw PDF parser
|
||||
logger.warn('Main PDF parser failed, using raw parser for buffer:', error)
|
||||
const { RawPdfParser } = await import('../../../../lib/file-parsers/raw-pdf-parser')
|
||||
const { RawPdfParser } = await import('@/lib/file-parsers/raw-pdf-parser')
|
||||
const rawParser = new RawPdfParser()
|
||||
|
||||
return await rawParser.parseBuffer(buffer)
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getStorageProvider, isUsingCloudStorage } from '@/lib/uploads'
|
||||
import { getBlobServiceClient } from '@/lib/uploads/blob/blob-client'
|
||||
import { getS3Client, sanitizeFilenameForMetadata } from '@/lib/uploads/s3/s3-client'
|
||||
import { BLOB_CONFIG, BLOB_KB_CONFIG, S3_CONFIG, S3_KB_CONFIG } from '@/lib/uploads/setup'
|
||||
import { createErrorResponse, createOptionsResponse } from '../utils'
|
||||
import { createErrorResponse, createOptionsResponse } from '@/app/api/files/utils'
|
||||
|
||||
const logger = createLogger('PresignedUploadAPI')
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
FileNotFoundError,
|
||||
findLocalFile,
|
||||
getContentType,
|
||||
} from '../../utils'
|
||||
} from '@/app/api/files/utils'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from '@/lib/billing/validation/seat-management'
|
||||
import { sendEmail } from '@/lib/email/mailer'
|
||||
import { validateAndNormalizeEmail } from '@/lib/email/utils'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { hasWorkspaceAdminAccess } from '@/lib/permissions/utils'
|
||||
import { db } from '@/db'
|
||||
@@ -344,7 +345,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
organizationEntry[0]?.name || 'organization',
|
||||
role,
|
||||
workspaceInvitationsWithNames,
|
||||
`${process.env.NEXT_PUBLIC_BASE_URL}/api/organizations/invitations/accept?id=${orgInvitation.id}`
|
||||
`${env.NEXT_PUBLIC_APP_URL}/api/organizations/invitations/accept?id=${orgInvitation.id}`
|
||||
)
|
||||
|
||||
emailResult = await sendEmail({
|
||||
@@ -357,7 +358,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
const emailHtml = await renderInvitationEmail(
|
||||
inviter[0]?.name || 'Someone',
|
||||
organizationEntry[0]?.name || 'organization',
|
||||
`${process.env.NEXT_PUBLIC_BASE_URL}/api/organizations/invitations/accept?id=${orgInvitation.id}`,
|
||||
`${env.NEXT_PUBLIC_APP_URL}/api/organizations/invitations/accept?id=${orgInvitation.id}`,
|
||||
email
|
||||
)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getSession } from '@/lib/auth'
|
||||
import { validateSeatAvailability } from '@/lib/billing/validation/seat-management'
|
||||
import { sendEmail } from '@/lib/email/mailer'
|
||||
import { validateAndNormalizeEmail } from '@/lib/email/utils'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { db } from '@/db'
|
||||
import { invitation, member, organization, user, userStats } from '@/db/schema'
|
||||
@@ -246,7 +247,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
const emailHtml = await renderInvitationEmail(
|
||||
inviter[0]?.name || 'Someone',
|
||||
organizationEntry[0]?.name || 'organization',
|
||||
`${process.env.NEXT_PUBLIC_BASE_URL}/api/organizations/invitations/accept?id=${invitationId}`,
|
||||
`${env.NEXT_PUBLIC_APP_URL}/api/organizations/invitations/accept?id=${invitationId}`,
|
||||
normalizedEmail
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { executeTool } from '@/tools'
|
||||
import { getTool, validateToolRequest } from '@/tools/utils'
|
||||
@@ -51,14 +52,14 @@ const createErrorResponse = (error: any, status = 500, additionalData = {}) => {
|
||||
logger.error('Creating error response', {
|
||||
errorMessage,
|
||||
status,
|
||||
stack: process.env.NODE_ENV === 'development' ? errorStack : undefined,
|
||||
stack: isDev ? errorStack : undefined,
|
||||
})
|
||||
|
||||
return formatResponse(
|
||||
{
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
stack: process.env.NODE_ENV === 'development' ? errorStack : undefined,
|
||||
stack: isDev ? errorStack : undefined,
|
||||
...additionalData,
|
||||
},
|
||||
status
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
|
||||
const logger = createLogger('TelemetryAPI')
|
||||
@@ -101,7 +102,7 @@ async function forwardToCollector(data: any): Promise<boolean> {
|
||||
},
|
||||
{
|
||||
key: 'deployment.environment',
|
||||
value: { stringValue: env.NODE_ENV || 'production' },
|
||||
value: { stringValue: isProd ? 'production' : 'development' },
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import crypto from 'crypto'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { saveWorkflowToNormalizedTables } from '@/lib/workflows/db-helpers'
|
||||
import { db } from '@/db'
|
||||
@@ -88,7 +89,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
|
||||
// Notify socket server about the revert operation for real-time sync
|
||||
try {
|
||||
const socketServerUrl = process.env.SOCKET_SERVER_URL || 'http://localhost:3002'
|
||||
const socketServerUrl = env.SOCKET_SERVER_URL || 'http://localhost:3002'
|
||||
await fetch(`${socketServerUrl}/api/workflow-reverted`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
AlertDialogTitle,
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { getNodeEnv } from '@/lib/environment'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { useGeneralStore } from '@/stores/settings/general/store'
|
||||
|
||||
@@ -50,7 +50,6 @@ export function TelemetryConsentDialog() {
|
||||
const loadSettings = useGeneralStore((state) => state.loadSettings)
|
||||
|
||||
const hasShownDialogThisSession = useRef(false)
|
||||
const isDevelopment = getNodeEnv() === 'development'
|
||||
|
||||
const isChatSubdomainOrPath =
|
||||
typeof window !== 'undefined' &&
|
||||
@@ -116,7 +115,7 @@ export function TelemetryConsentDialog() {
|
||||
telemetryNotifiedUser,
|
||||
telemetryEnabled,
|
||||
hasShownInSession: hasShownDialogThisSession.current,
|
||||
environment: getNodeEnv(),
|
||||
environment: isDev,
|
||||
})
|
||||
|
||||
const localStorageNotified =
|
||||
@@ -134,11 +133,11 @@ export function TelemetryConsentDialog() {
|
||||
!localStorageNotified &&
|
||||
telemetryEnabled &&
|
||||
!hasShownDialogThisSession.current &&
|
||||
isDevelopment
|
||||
isDev
|
||||
) {
|
||||
setOpen(true)
|
||||
hasShownDialogThisSession.current = true
|
||||
} else if (settingsLoaded && !telemetryNotifiedUser && !isDevelopment) {
|
||||
} else if (settingsLoaded && !telemetryNotifiedUser && !isDev) {
|
||||
// Auto-notify in non-development environments
|
||||
setTelemetryNotifiedUser(true)
|
||||
if (typeof window !== 'undefined') {
|
||||
|
||||
@@ -30,7 +30,7 @@ import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { env } from '@/lib/env'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { getBaseDomain } from '@/lib/urls/utils'
|
||||
import { cn } from '@/lib/utils'
|
||||
@@ -55,7 +55,7 @@ interface ChatDeployProps {
|
||||
type AuthType = 'public' | 'password' | 'email'
|
||||
|
||||
const getDomainSuffix = (() => {
|
||||
const suffix = env.NODE_ENV === 'development' ? `.${getBaseDomain()}` : '.simstudio.ai'
|
||||
const suffix = isDev ? `.${getBaseDomain()}` : '.simstudio.ai'
|
||||
return () => suffix
|
||||
})()
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useParams, usePathname, useRouter } from 'next/navigation'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import { useSession } from '@/lib/auth-client'
|
||||
import { env } from '@/lib/env'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import {
|
||||
getKeyboardShortcutText,
|
||||
@@ -28,8 +28,6 @@ import { WorkspaceHeader } from './components/workspace-header/workspace-header'
|
||||
|
||||
const logger = createLogger('Sidebar')
|
||||
|
||||
const IS_DEV = env.NODE_ENV === 'development'
|
||||
|
||||
export function Sidebar() {
|
||||
useGlobalShortcuts()
|
||||
|
||||
@@ -239,7 +237,7 @@ export function Sidebar() {
|
||||
{isCollapsed ? (
|
||||
<div className='flex-shrink-0 px-3 pt-1 pb-3'>
|
||||
<div className='flex flex-col space-y-[1px]'>
|
||||
{!IS_DEV && (
|
||||
{!isDev && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
@@ -286,7 +284,7 @@ export function Sidebar() {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{!IS_DEV && (
|
||||
{!isDev && (
|
||||
<div className='flex-shrink-0 px-3 pt-1'>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
@@ -343,7 +341,7 @@ export function Sidebar() {
|
||||
{/* Modals */}
|
||||
<SettingsModal open={showSettings} onOpenChange={setShowSettings} />
|
||||
<HelpModal open={showHelp} onOpenChange={setShowHelp} />
|
||||
{!IS_DEV && <InviteModal open={showInviteMembers} onOpenChange={setShowInviteMembers} />}
|
||||
{!isDev && <InviteModal open={showInviteMembers} onOpenChange={setShowInviteMembers} />}
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { DocumentIcon } from '@/components/icons'
|
||||
import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import type { FileParserOutput } from '@/tools/file/types'
|
||||
import type { BlockConfig, SubBlockConfig, SubBlockLayout, SubBlockType } from '../types'
|
||||
|
||||
const logger = createLogger('FileBlock')
|
||||
|
||||
const shouldEnableURLInput = env.NODE_ENV === 'production'
|
||||
const shouldEnableURLInput = isProd
|
||||
|
||||
const inputMethodBlock: SubBlockConfig = {
|
||||
id: 'inputMethod',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { MistralIcon } from '@/components/icons'
|
||||
import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
import type { MistralParserOutput } from '@/tools/mistral/types'
|
||||
import type { BlockConfig, SubBlockConfig, SubBlockLayout, SubBlockType } from '../types'
|
||||
|
||||
const shouldEnableFileUpload = env.NODE_ENV === 'production'
|
||||
const shouldEnableFileUpload = isProd
|
||||
|
||||
const inputMethodBlock: SubBlockConfig = {
|
||||
id: 'inputMethod',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js'
|
||||
import postgres from 'postgres'
|
||||
import { env } from '@/lib/env'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import * as schema from './schema'
|
||||
|
||||
// In production, use the Vercel-generated POSTGRES_URL
|
||||
@@ -38,4 +39,4 @@ declare global {
|
||||
}
|
||||
|
||||
export const db = global.database || drizzleClient
|
||||
if (env.NODE_ENV !== 'production') global.database = db
|
||||
if (isDev) global.database = db
|
||||
|
||||
@@ -46,9 +46,9 @@ export function useUserPermissions(
|
||||
}
|
||||
}
|
||||
|
||||
// Find current user in workspace permissions
|
||||
// Find current user in workspace permissions (case-insensitive)
|
||||
const currentUser = workspacePermissions?.users?.find(
|
||||
(user) => user.email === session.user.email
|
||||
(user) => user.email.toLowerCase() === session.user.email.toLowerCase()
|
||||
)
|
||||
|
||||
// If user not found in workspace, they have no permissions
|
||||
|
||||
@@ -18,18 +18,14 @@ import {
|
||||
linkedErrorsIntegration,
|
||||
makeFetchTransport,
|
||||
} from '@sentry/nextjs'
|
||||
|
||||
const clientEnv = {
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
NEXT_TELEMETRY_DISABLED: process.env.NEXT_TELEMETRY_DISABLED,
|
||||
}
|
||||
import { env } from './lib/env'
|
||||
import { isProd } from './lib/environment'
|
||||
|
||||
// Only in production
|
||||
if (typeof window !== 'undefined' && clientEnv.NODE_ENV === 'production') {
|
||||
if (typeof window !== 'undefined' && isProd) {
|
||||
const client = new BrowserClient({
|
||||
dsn: clientEnv.NEXT_PUBLIC_SENTRY_DSN || undefined,
|
||||
environment: clientEnv.NODE_ENV || 'development',
|
||||
dsn: env.NEXT_PUBLIC_SENTRY_DSN || undefined,
|
||||
environment: env.NODE_ENV || 'development',
|
||||
transport: makeFetchTransport,
|
||||
stackParser: defaultStackParser,
|
||||
integrations: [breadcrumbsIntegration(), dedupeIntegration(), linkedErrorsIntegration()],
|
||||
@@ -45,15 +41,14 @@ if (typeof window !== 'undefined' && clientEnv.NODE_ENV === 'production') {
|
||||
client.init()
|
||||
}
|
||||
|
||||
export const onRouterTransitionStart =
|
||||
clientEnv.NODE_ENV === 'production' ? captureRouterTransitionStart : () => {}
|
||||
export const onRouterTransitionStart = isProd ? captureRouterTransitionStart : () => {}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
const TELEMETRY_STATUS_KEY = 'simstudio-telemetry-status'
|
||||
let telemetryEnabled = true
|
||||
|
||||
try {
|
||||
if (clientEnv.NEXT_TELEMETRY_DISABLED === '1') {
|
||||
if (env.NEXT_TELEMETRY_DISABLED === '1') {
|
||||
telemetryEnabled = false
|
||||
} else {
|
||||
const storedPreference = localStorage.getItem(TELEMETRY_STATUS_KEY)
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
*
|
||||
* This file contains all server-side instrumentation logic.
|
||||
*/
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from './lib/env.ts'
|
||||
|
||||
const Sentry =
|
||||
process.env.NODE_ENV === 'production'
|
||||
? require('@sentry/nextjs')
|
||||
: { captureRequestError: () => {} }
|
||||
import { env } from './lib/env'
|
||||
import { isProd } from './lib/environment'
|
||||
import { createLogger } from './lib/logs/console-logger'
|
||||
|
||||
const Sentry = isProd ? require('@sentry/nextjs') : { captureRequestError: () => {} }
|
||||
|
||||
const logger = createLogger('OtelInstrumentation')
|
||||
|
||||
@@ -103,7 +102,7 @@ async function initializeOpenTelemetry() {
|
||||
}
|
||||
|
||||
async function initializeSentry() {
|
||||
if (env.NODE_ENV !== 'production') return
|
||||
if (!isProd) return
|
||||
|
||||
try {
|
||||
const Sentry = await import('@sentry/nextjs')
|
||||
|
||||
@@ -2,26 +2,19 @@ import { stripeClient } from '@better-auth/stripe/client'
|
||||
import { emailOTPClient, genericOAuthClient, organizationClient } from 'better-auth/client/plugins'
|
||||
import { createAuthClient } from 'better-auth/react'
|
||||
import { env } from './env'
|
||||
|
||||
const clientEnv = {
|
||||
NEXT_PUBLIC_VERCEL_URL: env.NEXT_PUBLIC_VERCEL_URL,
|
||||
NEXT_PUBLIC_APP_URL: env.NEXT_PUBLIC_APP_URL,
|
||||
NODE_ENV: env.NODE_ENV,
|
||||
VERCEL_ENV: env.VERCEL_ENV || '',
|
||||
BETTER_AUTH_URL: env.BETTER_AUTH_URL,
|
||||
}
|
||||
import { isDev, isProd } from './environment'
|
||||
|
||||
export function getBaseURL() {
|
||||
let baseURL
|
||||
|
||||
if (clientEnv.VERCEL_ENV === 'preview') {
|
||||
baseURL = `https://${clientEnv.NEXT_PUBLIC_VERCEL_URL}`
|
||||
} else if (clientEnv.VERCEL_ENV === 'development') {
|
||||
baseURL = `https://${clientEnv.NEXT_PUBLIC_VERCEL_URL}`
|
||||
} else if (clientEnv.VERCEL_ENV === 'production') {
|
||||
baseURL = clientEnv.BETTER_AUTH_URL || clientEnv.NEXT_PUBLIC_APP_URL
|
||||
} else if (clientEnv.NODE_ENV === 'development') {
|
||||
baseURL = clientEnv.NEXT_PUBLIC_APP_URL || clientEnv.BETTER_AUTH_URL || 'http://localhost:3000'
|
||||
if (env.VERCEL_ENV === 'preview') {
|
||||
baseURL = `https://${env.NEXT_PUBLIC_VERCEL_URL}`
|
||||
} else if (env.VERCEL_ENV === 'development') {
|
||||
baseURL = `https://${env.NEXT_PUBLIC_VERCEL_URL}`
|
||||
} else if (env.VERCEL_ENV === 'production') {
|
||||
baseURL = env.BETTER_AUTH_URL || env.NEXT_PUBLIC_APP_URL
|
||||
} else if (env.NODE_ENV === 'development') {
|
||||
baseURL = env.NEXT_PUBLIC_APP_URL || env.BETTER_AUTH_URL || 'http://localhost:3000'
|
||||
}
|
||||
|
||||
return baseURL
|
||||
@@ -33,7 +26,7 @@ export const client = createAuthClient({
|
||||
emailOTPClient(),
|
||||
genericOAuthClient(),
|
||||
// Only include Stripe client in production
|
||||
...(clientEnv.NODE_ENV === 'production'
|
||||
...(isProd
|
||||
? [
|
||||
stripeClient({
|
||||
subscription: true, // Enable subscription management
|
||||
@@ -48,7 +41,7 @@ export const { useSession, useActiveOrganization } = client
|
||||
|
||||
export const useSubscription = () => {
|
||||
// In development, provide mock implementations
|
||||
if (clientEnv.NODE_ENV === 'development') {
|
||||
if (isDev) {
|
||||
return {
|
||||
list: async () => ({ data: [] }),
|
||||
upgrade: async () => ({
|
||||
|
||||
@@ -19,17 +19,16 @@ import {
|
||||
renderOTPEmail,
|
||||
renderPasswordResetEmail,
|
||||
} from '@/components/emails/render-email'
|
||||
import { env, isTruthy } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { getEmailDomain } from '@/lib/urls/utils'
|
||||
import { db } from '@/db'
|
||||
import * as schema from '@/db/schema'
|
||||
import { getBaseURL } from './auth-client'
|
||||
import { env, isTruthy } from './env'
|
||||
import { getEmailDomain } from './urls/utils'
|
||||
|
||||
const logger = createLogger('Auth')
|
||||
|
||||
const isProd = env.NODE_ENV === 'production'
|
||||
|
||||
// Only initialize Stripe if the key is provided
|
||||
// This allows local development without a Stripe account
|
||||
const validStripeKey =
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs/promises'
|
||||
import path from 'path'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { generateEmbeddings } from '@/app/api/knowledge/utils'
|
||||
import { TextChunker } from './chunker'
|
||||
@@ -28,7 +29,6 @@ export class DocsChunker {
|
||||
overlap: options.overlap ?? 50,
|
||||
})
|
||||
// Use localhost docs in development, production docs otherwise
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
this.baseUrl =
|
||||
options.baseUrl ?? (isDev ? 'http://localhost:3001' : 'https://docs.simstudio.ai')
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { createEnv } from '@t3-oss/env-nextjs'
|
||||
import { env as runtimeEnv } from 'next-runtime-env'
|
||||
import { z } from 'zod'
|
||||
|
||||
const getEnv = (variable: string) => runtimeEnv(variable) ?? process.env[variable]
|
||||
|
||||
export const env = createEnv({
|
||||
skipValidation: true,
|
||||
|
||||
@@ -48,7 +45,6 @@ export const env = createEnv({
|
||||
SENTRY_PROJECT: z.string().optional(),
|
||||
SENTRY_AUTH_TOKEN: z.string().optional(),
|
||||
REDIS_URL: z.string().url().optional(),
|
||||
NEXT_TELEMETRY_DISABLED: z.string().optional(),
|
||||
NEXT_RUNTIME: z.string().optional(),
|
||||
VERCEL_ENV: z.string().optional(),
|
||||
|
||||
@@ -68,7 +64,6 @@ export const env = createEnv({
|
||||
// Miscellaneous
|
||||
CRON_SECRET: z.string().optional(),
|
||||
FREE_PLAN_LOG_RETENTION_DAYS: z.string().optional(),
|
||||
NODE_ENV: z.string().optional(),
|
||||
GITHUB_TOKEN: z.string().optional(),
|
||||
ELEVENLABS_API_KEY: z.string().min(1).optional(),
|
||||
AZURE_OPENAI_ENDPOINT: z.string().url().optional(),
|
||||
@@ -111,6 +106,7 @@ export const env = createEnv({
|
||||
SOCKET_SERVER_URL: z.string().url().optional(),
|
||||
SOCKET_PORT: z.number().optional(),
|
||||
PORT: z.number().optional(),
|
||||
ALLOWED_ORIGINS: z.string().optional(),
|
||||
},
|
||||
|
||||
client: {
|
||||
@@ -123,15 +119,22 @@ export const env = createEnv({
|
||||
NEXT_PUBLIC_SOCKET_URL: z.string().url().optional(),
|
||||
},
|
||||
|
||||
// Only need to define client variables, server variables are automatically handled
|
||||
// Variables available on both server and client
|
||||
shared: {
|
||||
NODE_ENV: z.enum(['development', 'test', 'production']).optional(),
|
||||
NEXT_TELEMETRY_DISABLED: z.string().optional(),
|
||||
},
|
||||
|
||||
experimental__runtimeEnv: {
|
||||
NEXT_PUBLIC_APP_URL: getEnv('NEXT_PUBLIC_APP_URL'),
|
||||
NEXT_PUBLIC_VERCEL_URL: getEnv('NEXT_PUBLIC_VERCEL_URL'),
|
||||
NEXT_PUBLIC_SENTRY_DSN: getEnv('NEXT_PUBLIC_SENTRY_DSN'),
|
||||
NEXT_PUBLIC_GOOGLE_CLIENT_ID: getEnv('NEXT_PUBLIC_GOOGLE_CLIENT_ID'),
|
||||
NEXT_PUBLIC_GOOGLE_API_KEY: getEnv('NEXT_PUBLIC_GOOGLE_API_KEY'),
|
||||
NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER: getEnv('NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER'),
|
||||
NEXT_PUBLIC_SOCKET_URL: getEnv('NEXT_PUBLIC_SOCKET_URL'),
|
||||
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
|
||||
NEXT_PUBLIC_VERCEL_URL: process.env.VERCEL_URL,
|
||||
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
NEXT_PUBLIC_GOOGLE_CLIENT_ID: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
|
||||
NEXT_PUBLIC_GOOGLE_API_KEY: process.env.NEXT_PUBLIC_GOOGLE_API_KEY,
|
||||
NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER: process.env.NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER,
|
||||
NEXT_PUBLIC_SOCKET_URL: process.env.NEXT_PUBLIC_SOCKET_URL,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
NEXT_TELEMETRY_DISABLED: process.env.NEXT_TELEMETRY_DISABLED,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -3,28 +3,20 @@
|
||||
*/
|
||||
import { env } from './env'
|
||||
|
||||
export const getNodeEnv = () => {
|
||||
try {
|
||||
return env.NODE_ENV
|
||||
} catch {
|
||||
return process.env.NODE_ENV
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the application running in production mode
|
||||
*/
|
||||
export const isProd = getNodeEnv() === 'production'
|
||||
export const isProd = env.NODE_ENV === 'production'
|
||||
|
||||
/**
|
||||
* Is the application running in development mode
|
||||
*/
|
||||
export const isDev = getNodeEnv() === 'development'
|
||||
export const isDev = env.NODE_ENV === 'development'
|
||||
|
||||
/**
|
||||
* Is the application running in test mode
|
||||
*/
|
||||
export const isTest = getNodeEnv() === 'test'
|
||||
export const isTest = env.NODE_ENV === 'test'
|
||||
|
||||
/**
|
||||
* Is this the hosted version of the application
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FreestyleSandboxes } from 'freestyle-sandboxes'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from './env'
|
||||
|
||||
const logger = createLogger('Freestyle')
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import OpenAI from 'openai'
|
||||
import { env } from './env'
|
||||
import { env } from '@/lib/env'
|
||||
|
||||
/**
|
||||
* Generates a short title for a chat based on the first message
|
||||
|
||||
@@ -44,8 +44,8 @@ const LOG_CONFIG = {
|
||||
colorize: true,
|
||||
},
|
||||
production: {
|
||||
enabled: true,
|
||||
minLevel: LogLevel.INFO, // Only show INFO and above in production
|
||||
enabled: false, // Disable all console logs in production
|
||||
minLevel: LogLevel.ERROR,
|
||||
colorize: false,
|
||||
},
|
||||
test: {
|
||||
|
||||
@@ -23,8 +23,8 @@ import {
|
||||
WealthboxIcon,
|
||||
xIcon,
|
||||
} from '@/components/icons'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from '../env'
|
||||
|
||||
const logger = createLogger('OAuth')
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Redis from 'ioredis'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from './env'
|
||||
|
||||
const logger = createLogger('Redis')
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
* Please maintain ethical telemetry practices if modified.
|
||||
*/
|
||||
import { DiagConsoleLogger, DiagLogLevel, diag } from '@opentelemetry/api'
|
||||
import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from './env'
|
||||
|
||||
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR)
|
||||
|
||||
@@ -142,7 +143,7 @@ function initializeClientTelemetry(): void {
|
||||
return
|
||||
}
|
||||
|
||||
if (env.NODE_ENV === 'production') {
|
||||
if (isProd) {
|
||||
trackEvent('page_view', window.location.pathname)
|
||||
|
||||
if (typeof window.history !== 'undefined') {
|
||||
@@ -265,7 +266,7 @@ export async function trackEvent(
|
||||
if (!status.enabled) return
|
||||
|
||||
try {
|
||||
if (env.NODE_ENV === 'production') {
|
||||
if (isProd) {
|
||||
await fetch('/api/telemetry', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
S3Client,
|
||||
} from '@aws-sdk/client-s3'
|
||||
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
|
||||
import { env } from '../../env'
|
||||
import { S3_CONFIG } from '../setup'
|
||||
import { env } from '@/lib/env'
|
||||
import { S3_CONFIG } from '@/lib/uploads/setup'
|
||||
|
||||
// Lazily create a single S3 client instance.
|
||||
let _s3Client: S3Client | null = null
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from '../env'
|
||||
import {
|
||||
ensureUploadsDirectory,
|
||||
getStorageProvider,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { existsSync } from 'fs'
|
||||
import { mkdir } from 'fs/promises'
|
||||
import path, { join } from 'path'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from '../env'
|
||||
|
||||
const logger = createLogger('UploadsSetup')
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { env } from '../env'
|
||||
import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
|
||||
/**
|
||||
* Returns the base URL of the application, respecting environment variables for deployment environments
|
||||
@@ -15,7 +16,6 @@ export function getBaseUrl(): string {
|
||||
return baseUrl
|
||||
}
|
||||
|
||||
const isProd = env.NODE_ENV === 'production'
|
||||
const protocol = isProd ? 'https://' : 'http://'
|
||||
return `${protocol}${baseUrl}`
|
||||
}
|
||||
@@ -36,7 +36,6 @@ export function getBaseDomain(): string {
|
||||
try {
|
||||
return new URL(fallbackUrl).host
|
||||
} catch {
|
||||
const isProd = env.NODE_ENV === 'production'
|
||||
return isProd ? 'simstudio.ai' : 'localhost:3000'
|
||||
}
|
||||
}
|
||||
@@ -51,7 +50,6 @@ export function getEmailDomain(): string {
|
||||
const baseDomain = getBaseDomain()
|
||||
return baseDomain.startsWith('www.') ? baseDomain.substring(4) : baseDomain
|
||||
} catch (_e) {
|
||||
const isProd = env.NODE_ENV === 'production'
|
||||
return isProd ? 'simstudio.ai' : 'localhost:3000'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'
|
||||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { env } from './env'
|
||||
|
||||
const logger = createLogger('Utils')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { NextResponse } from 'next/server'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { db } from '@/db'
|
||||
import { userStats, workflow as workflowTable } from '@/db/schema'
|
||||
import type { ExecutionResult } from '@/executor/types'
|
||||
import type { WorkflowState } from '@/stores/workflows/workflow/types'
|
||||
import { env } from '../env'
|
||||
|
||||
const logger = createLogger('WorkflowUtils')
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { getSessionCookie } from 'better-auth/cookies'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { getBaseDomain } from '@/lib/urls/utils'
|
||||
import { env } from './lib/env'
|
||||
import { isDev } from './lib/environment'
|
||||
import { createLogger } from './lib/logs/console-logger'
|
||||
import { getBaseDomain } from './lib/urls/utils'
|
||||
|
||||
const logger = createLogger('Middleware')
|
||||
|
||||
// Environment flag to check if we're in development mode
|
||||
const isDevelopment = env.NODE_ENV === 'development'
|
||||
|
||||
const SUSPICIOUS_UA_PATTERNS = [
|
||||
/^\s*$/, // Empty user agents
|
||||
/\.\./, // Path traversal attempt
|
||||
@@ -36,7 +33,7 @@ export async function middleware(request: NextRequest) {
|
||||
|
||||
// Extract root domain from BASE_DOMAIN (e.g., "simstudio.ai" from "staging.simstudio.ai")
|
||||
const baseParts = BASE_DOMAIN.split('.')
|
||||
const rootDomain = isDevelopment
|
||||
const rootDomain = isDev
|
||||
? 'localhost'
|
||||
: baseParts.length >= 2
|
||||
? baseParts
|
||||
@@ -129,16 +126,6 @@ export async function middleware(request: NextRequest) {
|
||||
return NextResponse.next()
|
||||
}
|
||||
|
||||
// If self-hosted skip waitlist
|
||||
if (env.DOCKER_BUILD) {
|
||||
return NextResponse.next()
|
||||
}
|
||||
|
||||
// Skip waitlist protection for development environment
|
||||
if (isDevelopment) {
|
||||
return NextResponse.next()
|
||||
}
|
||||
|
||||
const userAgent = request.headers.get('user-agent') || ''
|
||||
|
||||
// Check if this is a webhook endpoint that should be exempt from User-Agent validation
|
||||
|
||||
@@ -2,6 +2,7 @@ import path from 'path'
|
||||
import { withSentryConfig } from '@sentry/nextjs'
|
||||
import type { NextConfig } from 'next'
|
||||
import { env, isTruthy } from './lib/env'
|
||||
import { isDev, isProd } from './lib/environment'
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
devIndicators: false,
|
||||
@@ -26,7 +27,7 @@ const nextConfig: NextConfig = {
|
||||
optimizeCss: true,
|
||||
turbopackSourceMaps: false,
|
||||
},
|
||||
...(env.NODE_ENV === 'development' && {
|
||||
...(isDev && {
|
||||
allowedDevOrigins: [
|
||||
...(env.NEXT_PUBLIC_APP_URL
|
||||
? (() => {
|
||||
@@ -152,8 +153,8 @@ const sentryConfig = {
|
||||
org: env.SENTRY_ORG || '',
|
||||
project: env.SENTRY_PROJECT || '',
|
||||
authToken: env.SENTRY_AUTH_TOKEN || undefined,
|
||||
disableSourceMapUpload: env.NODE_ENV !== 'production',
|
||||
autoInstrumentServerFunctions: env.NODE_ENV === 'production',
|
||||
disableSourceMapUpload: !isProd,
|
||||
autoInstrumentServerFunctions: isProd,
|
||||
bundleSizeOptimizations: {
|
||||
excludeDebugStatements: true,
|
||||
excludePerformanceMonitoring: true,
|
||||
@@ -163,6 +164,4 @@ const sentryConfig = {
|
||||
},
|
||||
}
|
||||
|
||||
export default env.NODE_ENV === 'development'
|
||||
? nextConfig
|
||||
: withSentryConfig(nextConfig, sentryConfig)
|
||||
export default isDev ? nextConfig : withSentryConfig(nextConfig, sentryConfig)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import path from 'path'
|
||||
import { sql } from 'drizzle-orm'
|
||||
import { DocsChunker } from '@/lib/documents/docs-chunker'
|
||||
import { isDev } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { db } from '@/db'
|
||||
import { docsEmbeddings } from '@/db/schema'
|
||||
@@ -38,11 +39,7 @@ async function processDocsEmbeddings(options: ProcessingOptions = {}) {
|
||||
clearExisting: options.clearExisting ?? false,
|
||||
docsPath: options.docsPath ?? path.join(process.cwd(), '../../apps/docs/content/docs'),
|
||||
// Use localhost docs in development, production docs otherwise
|
||||
baseUrl:
|
||||
options.baseUrl ??
|
||||
(process.env.NODE_ENV === 'development'
|
||||
? 'http://localhost:3001'
|
||||
: 'https://docs.simstudio.ai'),
|
||||
baseUrl: options.baseUrl ?? (isDev ? 'http://localhost:3001' : 'https://docs.simstudio.ai'),
|
||||
chunkSize: options.chunkSize ?? 300, // Max 300 tokens per chunk
|
||||
minChunkSize: options.minChunkSize ?? 100,
|
||||
overlap: options.overlap ?? 50,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { Server as HttpServer } from 'http'
|
||||
import { Server } from 'socket.io'
|
||||
import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
import { createLogger } from '../../lib/logs/console-logger'
|
||||
|
||||
const logger = createLogger('SocketIOConfig')
|
||||
@@ -9,11 +11,11 @@ const logger = createLogger('SocketIOConfig')
|
||||
*/
|
||||
function getAllowedOrigins(): string[] {
|
||||
const allowedOrigins = [
|
||||
process.env.NEXT_PUBLIC_APP_URL,
|
||||
process.env.VERCEL_URL,
|
||||
env.NEXT_PUBLIC_APP_URL,
|
||||
env.NEXT_PUBLIC_VERCEL_URL,
|
||||
'http://localhost:3000',
|
||||
'http://localhost:3001',
|
||||
...(process.env.ALLOWED_ORIGINS?.split(',') || []),
|
||||
...(env.ALLOWED_ORIGINS?.split(',') || []),
|
||||
].filter((url): url is string => Boolean(url))
|
||||
|
||||
logger.info('Socket.IO CORS configuration:', { allowedOrigins })
|
||||
@@ -46,7 +48,7 @@ export function createSocketIOServer(httpServer: HttpServer): Server {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'none', // Required for cross-origin cookies
|
||||
secure: process.env.NODE_ENV === 'production', // HTTPS in production
|
||||
secure: isProd, // HTTPS in production
|
||||
},
|
||||
})
|
||||
|
||||
@@ -56,7 +58,7 @@ export function createSocketIOServer(httpServer: HttpServer): Server {
|
||||
pingTimeout: 60000,
|
||||
pingInterval: 25000,
|
||||
maxHttpBufferSize: 1e6,
|
||||
cookieSecure: process.env.NODE_ENV === 'production',
|
||||
cookieSecure: isProd,
|
||||
corsCredentials: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { and, eq, or } from 'drizzle-orm'
|
||||
import { drizzle } from 'drizzle-orm/postgres-js'
|
||||
import postgres from 'postgres'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/db-helpers'
|
||||
import * as schema from '../../db/schema'
|
||||
import { workflow, workflowBlocks, workflowEdges, workflowSubflows } from '../../db/schema'
|
||||
import { env } from '../../lib/env'
|
||||
import { createLogger } from '../../lib/logs/console-logger'
|
||||
import { loadWorkflowFromNormalizedTables } from '../../lib/workflows/db-helpers'
|
||||
|
||||
const logger = createLogger('SocketDatabase')
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createServer } from 'http'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '../lib/logs/console-logger'
|
||||
import { createSocketIOServer } from './config/socket'
|
||||
import { setupAllHandlers } from './handlers'
|
||||
@@ -75,13 +76,13 @@ io.engine.on('connection_error', (err) => {
|
||||
})
|
||||
})
|
||||
|
||||
const PORT = Number(process.env.PORT || process.env.SOCKET_PORT || 3002)
|
||||
const PORT = Number(env.PORT || env.SOCKET_PORT || 3002)
|
||||
|
||||
logger.info('Starting Socket.IO server...', {
|
||||
port: PORT,
|
||||
nodeEnv: process.env.NODE_ENV,
|
||||
hasDatabase: !!process.env.DATABASE_URL,
|
||||
hasAuth: !!process.env.BETTER_AUTH_SECRET,
|
||||
nodeEnv: env.NODE_ENV,
|
||||
hasDatabase: !!env.DATABASE_URL,
|
||||
hasAuth: !!env.BETTER_AUTH_SECRET,
|
||||
})
|
||||
|
||||
httpServer.listen(PORT, '0.0.0.0', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Socket } from 'socket.io'
|
||||
import { auth } from '../../lib/auth'
|
||||
import { createLogger } from '../../lib/logs/console-logger'
|
||||
import { auth } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
|
||||
const logger = createLogger('SocketAuth')
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ import { and, eq, isNull } from 'drizzle-orm'
|
||||
import { drizzle } from 'drizzle-orm/postgres-js'
|
||||
import postgres from 'postgres'
|
||||
import type { Server } from 'socket.io'
|
||||
import * as schema from '../../db/schema'
|
||||
import { workflowBlocks, workflowEdges } from '../../db/schema'
|
||||
import { env } from '../../lib/env'
|
||||
import { createLogger } from '../../lib/logs/console-logger'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import * as schema from '@/db/schema'
|
||||
import { workflowBlocks, workflowEdges } from '@/db/schema'
|
||||
|
||||
// Create dedicated database connection for room manager
|
||||
const connectionString = env.POSTGRES_URL ?? env.DATABASE_URL
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { env } from '@/lib/env'
|
||||
import { getNodeEnv } from '@/lib/environment'
|
||||
import { isTest } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { getBaseUrl } from '@/lib/urls/utils'
|
||||
import type { HttpMethod, TableRow, ToolConfig } from '../types'
|
||||
@@ -109,7 +109,7 @@ const processUrl = (
|
||||
// Check if a URL needs proxy to avoid CORS/method restrictions
|
||||
const shouldUseProxy = (url: string): boolean => {
|
||||
// Skip proxying in test environment
|
||||
if (getNodeEnv() === 'test') {
|
||||
if (isTest) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user