mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-12 00:18:09 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2df65527d3 | ||
|
|
d0b69455e2 | ||
|
|
6028b1f5c0 | ||
|
|
658cf11299 | ||
|
|
6312df3a07 | ||
|
|
9de7a00373 | ||
|
|
325a666a8b |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -32,6 +32,7 @@ jobs:
|
||||
env:
|
||||
NODE_OPTIONS: '--no-warnings'
|
||||
NEXT_PUBLIC_APP_URL: 'https://www.sim.ai'
|
||||
DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/simstudio'
|
||||
ENCRYPTION_KEY: '7cf672e460e430c1fba707575c2b0e2ad5a99dddf9b7b7e3b5646e630861db1c' # dummy key for CI only
|
||||
run: bun run test
|
||||
|
||||
@@ -39,6 +40,7 @@ jobs:
|
||||
env:
|
||||
NODE_OPTIONS: '--no-warnings'
|
||||
NEXT_PUBLIC_APP_URL: 'https://www.sim.ai'
|
||||
DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/simstudio'
|
||||
STRIPE_SECRET_KEY: 'dummy_key_for_ci_only'
|
||||
STRIPE_WEBHOOK_SECRET: 'dummy_secret_for_ci_only'
|
||||
RESEND_API_KEY: 'dummy_key_for_ci_only'
|
||||
@@ -71,7 +73,7 @@ jobs:
|
||||
run: bun install
|
||||
|
||||
- name: Apply migrations
|
||||
working-directory: ./apps/sim
|
||||
working-directory: ./packages/db
|
||||
env:
|
||||
DATABASE_URL: ${{ github.ref == 'refs/heads/main' && secrets.DATABASE_URL || secrets.STAGING_DATABASE_URL }}
|
||||
run: bunx drizzle-kit migrate
|
||||
run: bunx drizzle-kit migrate --config=./drizzle.config.ts
|
||||
|
||||
@@ -125,10 +125,11 @@ Update your `.env` file with the database URL:
|
||||
DATABASE_URL="postgresql://postgres:your_password@localhost:5432/simstudio"
|
||||
```
|
||||
|
||||
4. Set up the database:
|
||||
4. Set up the database (from packages/db):
|
||||
|
||||
```bash
|
||||
bunx drizzle-kit migrate
|
||||
cd packages/db
|
||||
bunx drizzle-kit migrate --config=./drizzle.config.ts
|
||||
```
|
||||
|
||||
5. Start the development servers:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Sharepoint
|
||||
description: Read and create pages
|
||||
description: Work with pages and lists
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
@@ -61,7 +61,7 @@ In Sim, the SharePoint integration empowers your agents to create and access Sha
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Integrate Sharepoint into the workflow. Can read and create pages, and list sites. Requires OAuth.
|
||||
Integrate SharePoint into the workflow. Read/create pages, list sites, and work with lists (read, create, update items). Requires OAuth.
|
||||
|
||||
|
||||
|
||||
@@ -124,6 +124,65 @@ List details of all SharePoint sites
|
||||
| --------- | ---- | ----------- |
|
||||
| `site` | object | Information about the current SharePoint site |
|
||||
|
||||
### `sharepoint_create_list`
|
||||
|
||||
Create a new list in a SharePoint site
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `siteId` | string | No | The ID of the SharePoint site \(internal use\) |
|
||||
| `siteSelector` | string | No | Select the SharePoint site |
|
||||
| `listDisplayName` | string | Yes | Display name of the list to create |
|
||||
| `listDescription` | string | No | Description of the list |
|
||||
| `listTemplate` | string | No | List template name \(e.g., 'genericList'\) |
|
||||
| `pageContent` | string | No | Optional JSON of columns. Either a top-level array of column definitions or an object with \{ columns: \[...\] \}. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `list` | object | Created SharePoint list information |
|
||||
|
||||
### `sharepoint_get_list`
|
||||
|
||||
Get metadata (and optionally columns/items) for a SharePoint list
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `siteSelector` | string | No | Select the SharePoint site |
|
||||
| `siteId` | string | No | The ID of the SharePoint site \(internal use\) |
|
||||
| `listId` | string | No | The ID of the list to retrieve |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `list` | object | Information about the SharePoint list |
|
||||
|
||||
### `sharepoint_update_list`
|
||||
|
||||
Update the properties (fields) on a SharePoint list item
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `siteSelector` | string | No | Select the SharePoint site |
|
||||
| `siteId` | string | No | The ID of the SharePoint site \(internal use\) |
|
||||
| `listId` | string | No | The ID of the list containing the item |
|
||||
| `itemId` | string | Yes | The ID of the list item to update |
|
||||
| `listItemFields` | object | Yes | Field values to update on the list item |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `item` | object | Updated SharePoint list item |
|
||||
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
@@ -4,19 +4,9 @@ import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
|
||||
export async function getOAuthProviderStatus() {
|
||||
const githubAvailable = !!(
|
||||
env.GITHUB_CLIENT_ID &&
|
||||
env.GITHUB_CLIENT_SECRET &&
|
||||
env.GITHUB_CLIENT_ID !== 'placeholder' &&
|
||||
env.GITHUB_CLIENT_SECRET !== 'placeholder'
|
||||
)
|
||||
const githubAvailable = !!(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET)
|
||||
|
||||
const googleAvailable = !!(
|
||||
env.GOOGLE_CLIENT_ID &&
|
||||
env.GOOGLE_CLIENT_SECRET &&
|
||||
env.GOOGLE_CLIENT_ID !== 'placeholder' &&
|
||||
env.GOOGLE_CLIENT_SECRET !== 'placeholder'
|
||||
)
|
||||
const googleAvailable = !!(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET)
|
||||
|
||||
return { githubAvailable, googleAvailable, isProduction: isProd }
|
||||
}
|
||||
|
||||
@@ -37,12 +37,6 @@ export function SocialLoginButtons({
|
||||
setIsGithubLoading(true)
|
||||
try {
|
||||
await client.signIn.social({ provider: 'github', callbackURL })
|
||||
|
||||
// Mark that the user has previously logged in
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('has_logged_in_before', 'true')
|
||||
document.cookie = 'has_logged_in_before=true; path=/; max-age=31536000; SameSite=Lax' // 1 year expiry
|
||||
}
|
||||
} catch (err: any) {
|
||||
let errorMessage = 'Failed to sign in with GitHub'
|
||||
|
||||
@@ -66,13 +60,6 @@ export function SocialLoginButtons({
|
||||
setIsGoogleLoading(true)
|
||||
try {
|
||||
await client.signIn.social({ provider: 'google', callbackURL })
|
||||
|
||||
// Mark that the user has previously logged in
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('has_logged_in_before', 'true')
|
||||
// Also set a cookie to enable middleware to check login status
|
||||
document.cookie = 'has_logged_in_before=true; path=/; max-age=31536000; SameSite=Lax' // 1 year expiry
|
||||
}
|
||||
} catch (err: any) {
|
||||
let errorMessage = 'Failed to sign in with Google'
|
||||
|
||||
|
||||
@@ -74,12 +74,12 @@ const validatePassword = (passwordValue: string): string[] => {
|
||||
|
||||
if (!PASSWORD_VALIDATIONS.required.test(passwordValue)) {
|
||||
errors.push(PASSWORD_VALIDATIONS.required.message)
|
||||
return errors // Return early for required field
|
||||
return errors
|
||||
}
|
||||
|
||||
if (!PASSWORD_VALIDATIONS.notEmpty.test(passwordValue)) {
|
||||
errors.push(PASSWORD_VALIDATIONS.notEmpty.message)
|
||||
return errors // Return early for empty field
|
||||
return errors
|
||||
}
|
||||
|
||||
return errors
|
||||
@@ -104,11 +104,9 @@ export default function LoginPage({
|
||||
const [showValidationError, setShowValidationError] = useState(false)
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
|
||||
// Initialize state for URL parameters
|
||||
const [callbackUrl, setCallbackUrl] = useState('/workspace')
|
||||
const [isInviteFlow, setIsInviteFlow] = useState(false)
|
||||
|
||||
// Forgot password states
|
||||
const [forgotPasswordOpen, setForgotPasswordOpen] = useState(false)
|
||||
const [forgotPasswordEmail, setForgotPasswordEmail] = useState('')
|
||||
const [isSubmittingReset, setIsSubmittingReset] = useState(false)
|
||||
@@ -117,25 +115,20 @@ export default function LoginPage({
|
||||
message: string
|
||||
}>({ type: null, message: '' })
|
||||
|
||||
// Email validation state
|
||||
const [email, setEmail] = useState('')
|
||||
const [emailErrors, setEmailErrors] = useState<string[]>([])
|
||||
const [showEmailValidationError, setShowEmailValidationError] = useState(false)
|
||||
|
||||
// Extract URL parameters after component mounts to avoid SSR issues
|
||||
useEffect(() => {
|
||||
setMounted(true)
|
||||
|
||||
// Only access search params on the client side
|
||||
if (searchParams) {
|
||||
const callback = searchParams.get('callbackUrl')
|
||||
if (callback) {
|
||||
// Validate the callbackUrl before setting it
|
||||
if (validateCallbackUrl(callback)) {
|
||||
setCallbackUrl(callback)
|
||||
} else {
|
||||
logger.warn('Invalid callback URL detected and blocked:', { url: callback })
|
||||
// Keep the default safe value ('/workspace')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,12 +136,10 @@ export default function LoginPage({
|
||||
setIsInviteFlow(inviteFlow)
|
||||
}
|
||||
|
||||
// Check if CSS variable has been customized
|
||||
const checkCustomBrand = () => {
|
||||
const computedStyle = getComputedStyle(document.documentElement)
|
||||
const brandAccent = computedStyle.getPropertyValue('--brand-accent-hex').trim()
|
||||
|
||||
// Check if the CSS variable exists and is different from the default
|
||||
if (brandAccent && brandAccent !== '#6f3dfa') {
|
||||
setButtonClass('auth-button-custom')
|
||||
} else {
|
||||
@@ -158,7 +149,6 @@ export default function LoginPage({
|
||||
|
||||
checkCustomBrand()
|
||||
|
||||
// Also check on window resize or theme changes
|
||||
window.addEventListener('resize', checkCustomBrand)
|
||||
const observer = new MutationObserver(checkCustomBrand)
|
||||
observer.observe(document.documentElement, {
|
||||
@@ -189,7 +179,6 @@ export default function LoginPage({
|
||||
const newEmail = e.target.value
|
||||
setEmail(newEmail)
|
||||
|
||||
// Silently validate but don't show errors until submit
|
||||
const errors = validateEmailField(newEmail)
|
||||
setEmailErrors(errors)
|
||||
setShowEmailValidationError(false)
|
||||
@@ -199,7 +188,6 @@ export default function LoginPage({
|
||||
const newPassword = e.target.value
|
||||
setPassword(newPassword)
|
||||
|
||||
// Silently validate but don't show errors until submit
|
||||
const errors = validatePassword(newPassword)
|
||||
setPasswordErrors(errors)
|
||||
setShowValidationError(false)
|
||||
@@ -210,26 +198,23 @@ export default function LoginPage({
|
||||
setIsLoading(true)
|
||||
|
||||
const formData = new FormData(e.currentTarget)
|
||||
const email = formData.get('email') as string
|
||||
const emailRaw = formData.get('email') as string
|
||||
const email = emailRaw.trim().toLowerCase()
|
||||
|
||||
// Validate email on submit
|
||||
const emailValidationErrors = validateEmailField(email)
|
||||
setEmailErrors(emailValidationErrors)
|
||||
setShowEmailValidationError(emailValidationErrors.length > 0)
|
||||
|
||||
// Validate password on submit
|
||||
const passwordValidationErrors = validatePassword(password)
|
||||
setPasswordErrors(passwordValidationErrors)
|
||||
setShowValidationError(passwordValidationErrors.length > 0)
|
||||
|
||||
// If there are validation errors, stop submission
|
||||
if (emailValidationErrors.length > 0 || passwordValidationErrors.length > 0) {
|
||||
setIsLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// Final validation before submission
|
||||
const safeCallbackUrl = validateCallbackUrl(callbackUrl) ? callbackUrl : '/workspace'
|
||||
|
||||
const result = await client.signIn.email(
|
||||
@@ -291,33 +276,13 @@ export default function LoginPage({
|
||||
setIsLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
// Mark that the user has previously logged in
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('has_logged_in_before', 'true')
|
||||
document.cookie = 'has_logged_in_before=true; path=/; max-age=31536000; SameSite=Lax' // 1 year expiry
|
||||
}
|
||||
} catch (err: any) {
|
||||
// Handle only the special verification case that requires a redirect
|
||||
if (err.message?.includes('not verified') || err.code?.includes('EMAIL_NOT_VERIFIED')) {
|
||||
try {
|
||||
await client.emailOtp.sendVerificationOtp({
|
||||
email,
|
||||
type: 'email-verification',
|
||||
})
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
sessionStorage.setItem('verificationEmail', email)
|
||||
}
|
||||
|
||||
router.push('/verify')
|
||||
return
|
||||
} catch (_verifyErr) {
|
||||
setPasswordErrors(['Failed to send verification code. Please try again later.'])
|
||||
setShowValidationError(true)
|
||||
setIsLoading(false)
|
||||
return
|
||||
if (typeof window !== 'undefined') {
|
||||
sessionStorage.setItem('verificationEmail', email)
|
||||
}
|
||||
router.push('/verify')
|
||||
return
|
||||
}
|
||||
|
||||
console.error('Uncaught login error:', err)
|
||||
|
||||
@@ -24,7 +24,6 @@ function ResetPasswordContent() {
|
||||
text: '',
|
||||
})
|
||||
|
||||
// Validate token presence
|
||||
useEffect(() => {
|
||||
if (!token) {
|
||||
setStatusMessage({
|
||||
@@ -60,7 +59,6 @@ function ResetPasswordContent() {
|
||||
text: 'Password reset successful! Redirecting to login...',
|
||||
})
|
||||
|
||||
// Redirect to login page after 1.5 seconds
|
||||
setTimeout(() => {
|
||||
router.push('/login?resetSuccess=true')
|
||||
}, 1500)
|
||||
|
||||
@@ -30,12 +30,10 @@ export function RequestResetForm({
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
|
||||
useEffect(() => {
|
||||
// Check if CSS variable has been customized
|
||||
const checkCustomBrand = () => {
|
||||
const computedStyle = getComputedStyle(document.documentElement)
|
||||
const brandAccent = computedStyle.getPropertyValue('--brand-accent-hex').trim()
|
||||
|
||||
// Check if the CSS variable exists and is different from the default
|
||||
if (brandAccent && brandAccent !== '#6f3dfa') {
|
||||
setButtonClass('auth-button-custom')
|
||||
} else {
|
||||
@@ -45,7 +43,6 @@ export function RequestResetForm({
|
||||
|
||||
checkCustomBrand()
|
||||
|
||||
// Also check on window resize or theme changes
|
||||
window.addEventListener('resize', checkCustomBrand)
|
||||
const observer = new MutationObserver(checkCustomBrand)
|
||||
observer.observe(document.documentElement, {
|
||||
@@ -132,12 +129,10 @@ export function SetNewPasswordForm({
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
|
||||
useEffect(() => {
|
||||
// Check if CSS variable has been customized
|
||||
const checkCustomBrand = () => {
|
||||
const computedStyle = getComputedStyle(document.documentElement)
|
||||
const brandAccent = computedStyle.getPropertyValue('--brand-accent-hex').trim()
|
||||
|
||||
// Check if the CSS variable exists and is different from the default
|
||||
if (brandAccent && brandAccent !== '#6f3dfa') {
|
||||
setButtonClass('auth-button-custom')
|
||||
} else {
|
||||
@@ -147,7 +142,6 @@ export function SetNewPasswordForm({
|
||||
|
||||
checkCustomBrand()
|
||||
|
||||
// Also check on window resize or theme changes
|
||||
window.addEventListener('resize', checkCustomBrand)
|
||||
const observer = new MutationObserver(checkCustomBrand)
|
||||
observer.observe(document.documentElement, {
|
||||
@@ -164,7 +158,6 @@ export function SetNewPasswordForm({
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
// Simple validation
|
||||
if (password.length < 8) {
|
||||
setValidationMessage('Password must be at least 8 characters long')
|
||||
return
|
||||
|
||||
@@ -2,7 +2,6 @@ import { env, isTruthy } from '@/lib/env'
|
||||
import { getOAuthProviderStatus } from '@/app/(auth)/components/oauth-provider-checker'
|
||||
import SignupForm from '@/app/(auth)/signup/signup-form'
|
||||
|
||||
// Force dynamic rendering to avoid prerender errors with search params
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
export default async function SignupPage() {
|
||||
|
||||
@@ -95,7 +95,6 @@ function SignupFormContent({
|
||||
const [isInviteFlow, setIsInviteFlow] = useState(false)
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
|
||||
// Name validation state
|
||||
const [name, setName] = useState('')
|
||||
const [nameErrors, setNameErrors] = useState<string[]>([])
|
||||
const [showNameValidationError, setShowNameValidationError] = useState(false)
|
||||
@@ -107,29 +106,24 @@ function SignupFormContent({
|
||||
setEmail(emailParam)
|
||||
}
|
||||
|
||||
// Handle redirection for invitation flow
|
||||
const redirectParam = searchParams.get('redirect')
|
||||
if (redirectParam) {
|
||||
setRedirectUrl(redirectParam)
|
||||
|
||||
// Check if this is part of an invitation flow
|
||||
if (redirectParam.startsWith('/invite/')) {
|
||||
setIsInviteFlow(true)
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly check for invite_flow parameter
|
||||
const inviteFlowParam = searchParams.get('invite_flow')
|
||||
if (inviteFlowParam === 'true') {
|
||||
setIsInviteFlow(true)
|
||||
}
|
||||
|
||||
// Check if CSS variable has been customized
|
||||
const checkCustomBrand = () => {
|
||||
const computedStyle = getComputedStyle(document.documentElement)
|
||||
const brandAccent = computedStyle.getPropertyValue('--brand-accent-hex').trim()
|
||||
|
||||
// Check if the CSS variable exists and is different from the default
|
||||
if (brandAccent && brandAccent !== '#6f3dfa') {
|
||||
setButtonClass('auth-button-custom')
|
||||
} else {
|
||||
@@ -139,7 +133,6 @@ function SignupFormContent({
|
||||
|
||||
checkCustomBrand()
|
||||
|
||||
// Also check on window resize or theme changes
|
||||
window.addEventListener('resize', checkCustomBrand)
|
||||
const observer = new MutationObserver(checkCustomBrand)
|
||||
observer.observe(document.documentElement, {
|
||||
@@ -153,7 +146,6 @@ function SignupFormContent({
|
||||
}
|
||||
}, [searchParams])
|
||||
|
||||
// Validate password and return array of error messages
|
||||
const validatePassword = (passwordValue: string): string[] => {
|
||||
const errors: string[] = []
|
||||
|
||||
@@ -180,18 +172,17 @@ function SignupFormContent({
|
||||
return errors
|
||||
}
|
||||
|
||||
// Validate name and return array of error messages
|
||||
const validateName = (nameValue: string): string[] => {
|
||||
const errors: string[] = []
|
||||
|
||||
if (!NAME_VALIDATIONS.required.test(nameValue)) {
|
||||
errors.push(NAME_VALIDATIONS.required.message)
|
||||
return errors // Return early for required field
|
||||
return errors
|
||||
}
|
||||
|
||||
if (!NAME_VALIDATIONS.notEmpty.test(nameValue)) {
|
||||
errors.push(NAME_VALIDATIONS.notEmpty.message)
|
||||
return errors // Return early for empty field
|
||||
return errors
|
||||
}
|
||||
|
||||
if (!NAME_VALIDATIONS.validCharacters.regex.test(nameValue.trim())) {
|
||||
@@ -209,7 +200,6 @@ function SignupFormContent({
|
||||
const newPassword = e.target.value
|
||||
setPassword(newPassword)
|
||||
|
||||
// Silently validate but don't show errors
|
||||
const errors = validatePassword(newPassword)
|
||||
setPasswordErrors(errors)
|
||||
setShowValidationError(false)
|
||||
@@ -228,12 +218,10 @@ function SignupFormContent({
|
||||
const newEmail = e.target.value
|
||||
setEmail(newEmail)
|
||||
|
||||
// Silently validate but don't show errors until submit
|
||||
const errors = validateEmailField(newEmail)
|
||||
setEmailErrors(errors)
|
||||
setShowEmailValidationError(false)
|
||||
|
||||
// Clear any previous server-side email errors when the user starts typing
|
||||
if (emailError) {
|
||||
setEmailError('')
|
||||
}
|
||||
@@ -244,7 +232,8 @@ function SignupFormContent({
|
||||
setIsLoading(true)
|
||||
|
||||
const formData = new FormData(e.currentTarget)
|
||||
const emailValue = formData.get('email') as string
|
||||
const emailValueRaw = formData.get('email') as string
|
||||
const emailValue = emailValueRaw.trim().toLowerCase()
|
||||
const passwordValue = formData.get('password') as string
|
||||
const nameValue = formData.get('name') as string
|
||||
|
||||
@@ -348,7 +337,6 @@ function SignupFormContent({
|
||||
return
|
||||
}
|
||||
|
||||
// Refresh session to get the new user data immediately after signup
|
||||
try {
|
||||
await refetchSession()
|
||||
logger.info('Session refreshed after successful signup')
|
||||
@@ -356,34 +344,23 @@ function SignupFormContent({
|
||||
logger.error('Failed to refresh session after signup:', sessionError)
|
||||
}
|
||||
|
||||
// For new signups, always require verification
|
||||
if (typeof window !== 'undefined') {
|
||||
sessionStorage.setItem('verificationEmail', emailValue)
|
||||
localStorage.setItem('has_logged_in_before', 'true')
|
||||
|
||||
// Set cookie flag for middleware check
|
||||
document.cookie = 'requiresEmailVerification=true; path=/; max-age=900; SameSite=Lax' // 15 min expiry
|
||||
document.cookie = 'has_logged_in_before=true; path=/; max-age=31536000; SameSite=Lax'
|
||||
|
||||
// Store invitation flow state if applicable
|
||||
if (isInviteFlow && redirectUrl) {
|
||||
sessionStorage.setItem('inviteRedirectUrl', redirectUrl)
|
||||
sessionStorage.setItem('isInviteFlow', 'true')
|
||||
}
|
||||
}
|
||||
|
||||
// Send verification OTP manually
|
||||
try {
|
||||
await client.emailOtp.sendVerificationOtp({
|
||||
email: emailValue,
|
||||
type: 'email-verification',
|
||||
type: 'sign-in',
|
||||
})
|
||||
} catch (otpError) {
|
||||
logger.error('Failed to send OTP:', otpError)
|
||||
// Continue anyway - user can use resend button
|
||||
} catch (otpErr) {
|
||||
logger.warn('Failed to send sign-in OTP after signup; user can press Resend', otpErr)
|
||||
}
|
||||
|
||||
// Always redirect to verification for new signups
|
||||
router.push('/verify?fromSignup=true')
|
||||
} catch (error) {
|
||||
logger.error('Signup error:', error)
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { env } from '@/lib/env'
|
||||
import { isProd } from '@/lib/environment'
|
||||
import { getBaseUrl } from '@/lib/urls/utils'
|
||||
import { VerifyContent } from '@/app/(auth)/verify/verify-content'
|
||||
|
||||
// Force dynamic rendering to avoid prerender errors with search params
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
export default function VerifyPage() {
|
||||
const baseUrl = getBaseUrl()
|
||||
const hasResendKey = Boolean(env.RESEND_API_KEY && env.RESEND_API_KEY !== 'placeholder')
|
||||
const hasResendKey = Boolean(env.RESEND_API_KEY)
|
||||
|
||||
return <VerifyContent hasResendKey={hasResendKey} baseUrl={baseUrl} isProduction={isProd} />
|
||||
return <VerifyContent hasResendKey={hasResendKey} isProduction={isProd} />
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { client, useSession } from '@/lib/auth-client'
|
||||
import { env, isTruthy } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
|
||||
const logger = createLogger('useVerification')
|
||||
@@ -47,61 +46,39 @@ export function useVerification({
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
// Get stored email
|
||||
const storedEmail = sessionStorage.getItem('verificationEmail')
|
||||
if (storedEmail) {
|
||||
setEmail(storedEmail)
|
||||
}
|
||||
|
||||
// Check for redirect information
|
||||
const storedRedirectUrl = sessionStorage.getItem('inviteRedirectUrl')
|
||||
if (storedRedirectUrl) {
|
||||
setRedirectUrl(storedRedirectUrl)
|
||||
}
|
||||
|
||||
// Check if this is an invite flow
|
||||
const storedIsInviteFlow = sessionStorage.getItem('isInviteFlow')
|
||||
if (storedIsInviteFlow === 'true') {
|
||||
setIsInviteFlow(true)
|
||||
}
|
||||
}
|
||||
|
||||
// Also check URL parameters for redirect information
|
||||
const redirectParam = searchParams.get('redirectAfter')
|
||||
if (redirectParam) {
|
||||
setRedirectUrl(redirectParam)
|
||||
}
|
||||
|
||||
// Check for invite_flow parameter
|
||||
const inviteFlowParam = searchParams.get('invite_flow')
|
||||
if (inviteFlowParam === 'true') {
|
||||
setIsInviteFlow(true)
|
||||
}
|
||||
}, [searchParams])
|
||||
|
||||
// Send initial OTP code if this is the first load
|
||||
useEffect(() => {
|
||||
if (email && !isSendingInitialOtp && hasResendKey) {
|
||||
setIsSendingInitialOtp(true)
|
||||
|
||||
// Only send verification OTP if we're coming from login page
|
||||
// Skip this if coming from signup since the OTP is already sent
|
||||
if (!searchParams.get('fromSignup')) {
|
||||
client.emailOtp
|
||||
.sendVerificationOtp({
|
||||
email,
|
||||
type: 'email-verification',
|
||||
})
|
||||
.then(() => {})
|
||||
.catch((error) => {
|
||||
logger.error('Failed to send initial verification code:', error)
|
||||
setErrorMessage('Failed to send verification code. Please use the resend button.')
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [email, isSendingInitialOtp, searchParams, hasResendKey])
|
||||
}, [email, isSendingInitialOtp, hasResendKey])
|
||||
|
||||
// Enable the verify button when all 6 digits are entered
|
||||
const isOtpComplete = otp.length === 6
|
||||
|
||||
async function verifyCode() {
|
||||
@@ -112,25 +89,24 @@ export function useVerification({
|
||||
setErrorMessage('')
|
||||
|
||||
try {
|
||||
// Call the verification API with the OTP code
|
||||
const response = await client.emailOtp.verifyEmail({
|
||||
email,
|
||||
const normalizedEmail = email.trim().toLowerCase()
|
||||
const response = await client.signIn.emailOtp({
|
||||
email: normalizedEmail,
|
||||
otp,
|
||||
})
|
||||
|
||||
// Check if verification was successful
|
||||
if (response && !response.error) {
|
||||
setIsVerified(true)
|
||||
|
||||
// Clear verification requirements and session storage
|
||||
try {
|
||||
await refetchSession()
|
||||
} catch (e) {
|
||||
logger.warn('Failed to refetch session after verification', e)
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
sessionStorage.removeItem('verificationEmail')
|
||||
|
||||
// Clear the verification requirement flag
|
||||
document.cookie =
|
||||
'requiresEmailVerification=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
|
||||
|
||||
// Also clear invite-related items
|
||||
if (isInviteFlow) {
|
||||
sessionStorage.removeItem('inviteRedirectUrl')
|
||||
sessionStorage.removeItem('isInviteFlow')
|
||||
@@ -139,24 +115,20 @@ export function useVerification({
|
||||
|
||||
setTimeout(() => {
|
||||
if (isInviteFlow && redirectUrl) {
|
||||
// For invitation flow, redirect to the invitation page
|
||||
window.location.href = redirectUrl
|
||||
} else {
|
||||
// Default redirect to dashboard
|
||||
window.location.href = '/workspace'
|
||||
}
|
||||
}, 1000)
|
||||
} else {
|
||||
logger.info('Setting invalid OTP state - API error response')
|
||||
const message = 'Invalid verification code. Please check and try again.'
|
||||
// Set both state variables to ensure the error shows
|
||||
setIsInvalidOtp(true)
|
||||
setErrorMessage(message)
|
||||
logger.info('Error state after API error:', {
|
||||
isInvalidOtp: true,
|
||||
errorMessage: message,
|
||||
})
|
||||
// Clear the OTP input on invalid code
|
||||
setOtp('')
|
||||
}
|
||||
} catch (error: any) {
|
||||
@@ -171,7 +143,6 @@ export function useVerification({
|
||||
message = 'Too many failed attempts. Please request a new code.'
|
||||
}
|
||||
|
||||
// Set both state variables to ensure the error shows
|
||||
setIsInvalidOtp(true)
|
||||
setErrorMessage(message)
|
||||
logger.info('Error state after caught error:', {
|
||||
@@ -179,7 +150,6 @@ export function useVerification({
|
||||
errorMessage: message,
|
||||
})
|
||||
|
||||
// Clear the OTP input on error
|
||||
setOtp('')
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
@@ -192,10 +162,11 @@ export function useVerification({
|
||||
setIsLoading(true)
|
||||
setErrorMessage('')
|
||||
|
||||
const normalizedEmail = email.trim().toLowerCase()
|
||||
client.emailOtp
|
||||
.sendVerificationOtp({
|
||||
email,
|
||||
type: 'email-verification',
|
||||
email: normalizedEmail,
|
||||
type: 'sign-in',
|
||||
})
|
||||
.then(() => {})
|
||||
.catch(() => {
|
||||
@@ -207,7 +178,6 @@ export function useVerification({
|
||||
}
|
||||
|
||||
function handleOtpChange(value: string) {
|
||||
// Only clear error when user is actively typing a new code
|
||||
if (value.length === 6) {
|
||||
setIsInvalidOtp(false)
|
||||
setErrorMessage('')
|
||||
@@ -215,12 +185,11 @@ export function useVerification({
|
||||
setOtp(value)
|
||||
}
|
||||
|
||||
// Auto-submit when OTP is complete
|
||||
useEffect(() => {
|
||||
if (otp.length === 6 && email && !isLoading && !isVerified) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
verifyCode()
|
||||
}, 300) // Small delay to ensure UI is ready
|
||||
}, 300)
|
||||
|
||||
return () => clearTimeout(timeoutId)
|
||||
}
|
||||
@@ -229,17 +198,8 @@ export function useVerification({
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (!isProduction || !hasResendKey) {
|
||||
const storedEmail = sessionStorage.getItem('verificationEmail')
|
||||
}
|
||||
|
||||
const isDevOrDocker = !isProduction || isTruthy(env.DOCKER_BUILD)
|
||||
|
||||
if (isDevOrDocker || !hasResendKey) {
|
||||
setIsVerified(true)
|
||||
|
||||
document.cookie =
|
||||
'requiresEmailVerification=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
window.location.href = '/workspace'
|
||||
}, 1000)
|
||||
|
||||
@@ -11,7 +11,6 @@ import { soehne } from '@/app/fonts/soehne/soehne'
|
||||
|
||||
interface VerifyContentProps {
|
||||
hasResendKey: boolean
|
||||
baseUrl: string
|
||||
isProduction: boolean
|
||||
}
|
||||
|
||||
@@ -56,30 +55,13 @@ function VerificationForm({
|
||||
setCountdown(30)
|
||||
}
|
||||
|
||||
const handleCancelVerification = () => {
|
||||
// Clear verification data
|
||||
if (typeof window !== 'undefined') {
|
||||
sessionStorage.removeItem('verificationEmail')
|
||||
sessionStorage.removeItem('inviteRedirectUrl')
|
||||
sessionStorage.removeItem('isInviteFlow')
|
||||
|
||||
// Clear the verification requirement cookie
|
||||
document.cookie = 'requiresEmailVerification=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
|
||||
}
|
||||
|
||||
// Redirect to login
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
const [buttonClass, setButtonClass] = useState('auth-button-gradient')
|
||||
|
||||
useEffect(() => {
|
||||
// Check if CSS variable has been customized
|
||||
const checkCustomBrand = () => {
|
||||
const computedStyle = getComputedStyle(document.documentElement)
|
||||
const brandAccent = computedStyle.getPropertyValue('--brand-accent-hex').trim()
|
||||
|
||||
// Check if the CSS variable exists and is different from the default
|
||||
if (brandAccent && brandAccent !== '#6f3dfa') {
|
||||
setButtonClass('auth-button-custom')
|
||||
} else {
|
||||
@@ -89,7 +71,6 @@ function VerificationForm({
|
||||
|
||||
checkCustomBrand()
|
||||
|
||||
// Also check on window resize or theme changes
|
||||
window.addEventListener('resize', checkCustomBrand)
|
||||
const observer = new MutationObserver(checkCustomBrand)
|
||||
observer.observe(document.documentElement, {
|
||||
@@ -232,21 +213,27 @@ function VerificationForm({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* <div className='text-center font-light text-[14px]'>
|
||||
<div className='text-center font-light text-[14px]'>
|
||||
<button
|
||||
onClick={handleCancelVerification}
|
||||
onClick={() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
sessionStorage.removeItem('verificationEmail')
|
||||
sessionStorage.removeItem('inviteRedirectUrl')
|
||||
sessionStorage.removeItem('isInviteFlow')
|
||||
}
|
||||
router.push('/signup')
|
||||
}}
|
||||
className='font-medium text-[var(--brand-accent-hex)] underline-offset-4 transition hover:text-[var(--brand-accent-hover-hex)] hover:underline'
|
||||
>
|
||||
Back to login
|
||||
Back to signup
|
||||
</button>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// Fallback component while the verification form is loading
|
||||
function VerificationFormFallback() {
|
||||
return (
|
||||
<div className='text-center'>
|
||||
@@ -258,7 +245,7 @@ function VerificationFormFallback() {
|
||||
)
|
||||
}
|
||||
|
||||
export function VerifyContent({ hasResendKey, baseUrl, isProduction }: VerifyContentProps) {
|
||||
export function VerifyContent({ hasResendKey, isProduction }: VerifyContentProps) {
|
||||
return (
|
||||
<Suspense fallback={<VerificationFormFallback />}>
|
||||
<VerificationForm hasResendKey={hasResendKey} isProduction={isProduction} />
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
StripeIcon,
|
||||
SupabaseIcon,
|
||||
} from '@/components/icons'
|
||||
import { LandingPromptStorage } from '@/lib/browser-storage'
|
||||
import { soehne } from '@/app/fonts/soehne/soehne'
|
||||
import {
|
||||
CARD_WIDTH,
|
||||
@@ -271,6 +272,7 @@ export default function Hero() {
|
||||
*/
|
||||
const handleSubmit = () => {
|
||||
if (!isEmpty) {
|
||||
LandingPromptStorage.store(textValue)
|
||||
router.push('/signup')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ export function mockExecutionDependencies() {
|
||||
})),
|
||||
}))
|
||||
|
||||
vi.mock('@/db', () => ({
|
||||
vi.mock('@sim/db', () => ({
|
||||
db: mockDb,
|
||||
}))
|
||||
}
|
||||
@@ -395,7 +395,7 @@ export async function getMockedDependencies() {
|
||||
const workflowUtilsModule = await import('@/lib/workflows/utils')
|
||||
const executorModule = await import('@/executor')
|
||||
const serializerModule = await import('@/serializer')
|
||||
const dbModule = await import('@/db')
|
||||
const dbModule = await import('@sim/db')
|
||||
|
||||
return {
|
||||
decryptSecret: utilsModule.decryptSecret,
|
||||
@@ -428,7 +428,7 @@ export function mockScheduleStatusDb({
|
||||
schedule?: any[]
|
||||
workflow?: any[]
|
||||
} = {}) {
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
let callCount = 0
|
||||
|
||||
const select = vi.fn().mockImplementation(() => ({
|
||||
@@ -469,7 +469,7 @@ export function mockScheduleExecuteDb({
|
||||
workflowRecord?: any
|
||||
envRecord?: any
|
||||
}): void {
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
const select = vi.fn().mockImplementation(() => ({
|
||||
from: vi.fn().mockImplementation((table: any) => {
|
||||
const tbl = String(table)
|
||||
@@ -544,7 +544,7 @@ export function mockAuth(user: MockUser = mockUser): MockAuthResult {
|
||||
* Mock common schema patterns
|
||||
*/
|
||||
export function mockCommonSchemas() {
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
workflowFolder: {
|
||||
id: 'id',
|
||||
userId: 'userId',
|
||||
@@ -597,7 +597,7 @@ export function mockDrizzleOrm() {
|
||||
* Mock knowledge-related database schemas
|
||||
*/
|
||||
export function mockKnowledgeSchemas() {
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
knowledgeBase: {
|
||||
id: 'kb_id',
|
||||
userId: 'user_id',
|
||||
@@ -1091,7 +1091,7 @@ export function createMockDatabase(options: MockDatabaseOptions = {}) {
|
||||
transaction: createTransactionMock(),
|
||||
}
|
||||
|
||||
vi.doMock('@/db', () => ({ db: mockDb }))
|
||||
vi.doMock('@sim/db', () => ({ db: mockDb }))
|
||||
|
||||
return {
|
||||
mockDb,
|
||||
|
||||
@@ -34,13 +34,11 @@ describe('OAuth Connections API Route', () => {
|
||||
getSession: mockGetSession,
|
||||
}))
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDb,
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
account: { userId: 'userId', providerId: 'providerId' },
|
||||
user: { email: 'email', id: 'id' },
|
||||
eq: vi.fn((field, value) => ({ field, value, type: 'eq' })),
|
||||
}))
|
||||
|
||||
vi.doMock('drizzle-orm', () => ({
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { account, db, user } from '@sim/db'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { jwtDecode } from 'jwt-decode'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { account, user } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('OAuthConnectionsAPI')
|
||||
|
||||
|
||||
@@ -45,11 +45,11 @@ describe('OAuth Credentials API Route', () => {
|
||||
parseProvider: mockParseProvider,
|
||||
}))
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDb,
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
account: { userId: 'userId', providerId: 'providerId' },
|
||||
user: { email: 'email', id: 'id' },
|
||||
}))
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account, user, workflow } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { jwtDecode } from 'jwt-decode'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
@@ -7,8 +9,6 @@ import type { OAuthService } from '@/lib/oauth/oauth'
|
||||
import { parseProvider } from '@/lib/oauth/oauth'
|
||||
import { getUserEntityPermissions } from '@/lib/permissions/utils'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { account, user, workflow } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@ describe('OAuth Disconnect API Route', () => {
|
||||
getSession: mockGetSession,
|
||||
}))
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDb,
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
account: { userId: 'userId', providerId: 'providerId' },
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { and, eq, like, or } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('OAuth Utils', () => {
|
||||
getSession: vi.fn().mockResolvedValue(mockSession),
|
||||
}))
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDb,
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account, workflow } from '@sim/db/schema'
|
||||
import { and, desc, eq } from 'drizzle-orm'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { refreshOAuthToken } from '@/lib/oauth/oauth'
|
||||
import { db } from '@/db'
|
||||
import { account, workflow } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('OAuthUtilsAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { subscription as subscriptionTable, user } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { requireStripeClient } from '@/lib/billing/stripe-client'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { subscription as subscriptionTable, user } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('BillingPortal')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { member, userStats } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { getSimplifiedBillingSummary } from '@/lib/billing/core/billing'
|
||||
import { getOrganizationBillingData } from '@/lib/billing/core/organization'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { member, userStats } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('UnifiedBillingAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { userStats } from '@sim/db/schema'
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -5,8 +7,6 @@ import { checkInternalApiKey } from '@/lib/copilot/utils'
|
||||
import { isBillingEnabled } from '@/lib/environment'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { userStats } from '@/db/schema'
|
||||
import { calculateCost } from '@/providers/utils'
|
||||
|
||||
const logger = createLogger('billing-update-cost')
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { chat } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -8,8 +10,6 @@ import { getRedisClient, markMessageAsProcessed, releaseLock } from '@/lib/redis
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { addCorsHeaders, setChatAuthCookie } from '@/app/api/chat/utils'
|
||||
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
|
||||
import { db } from '@/db'
|
||||
import { chat } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('ChatOtpAPI')
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ describe('Chat Subdomain API Route', () => {
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
const mockSelect = vi.fn().mockImplementation((fields) => {
|
||||
if (fields && fields.isDeployed !== undefined) {
|
||||
return {
|
||||
@@ -153,7 +153,7 @@ describe('Chat Subdomain API Route', () => {
|
||||
})
|
||||
|
||||
it('should return 404 for non-existent subdomain', async () => {
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
const mockLimit = vi.fn().mockReturnValue([])
|
||||
const mockWhere = vi.fn().mockReturnValue({ limit: mockLimit })
|
||||
const mockFrom = vi.fn().mockReturnValue({ where: mockWhere })
|
||||
@@ -181,7 +181,7 @@ describe('Chat Subdomain API Route', () => {
|
||||
})
|
||||
|
||||
it('should return 403 for inactive chat', async () => {
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
const mockLimit = vi.fn().mockReturnValue([
|
||||
{
|
||||
id: 'chat-id',
|
||||
@@ -299,7 +299,7 @@ describe('Chat Subdomain API Route', () => {
|
||||
|
||||
it('should return 503 when workflow is not available', async () => {
|
||||
// Override the default workflow result to return non-deployed
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
// Track call count to return different results
|
||||
let callCount = 0
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { chat, workflow } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
@@ -10,8 +12,6 @@ import {
|
||||
validateChatAuth,
|
||||
} from '@/app/api/chat/utils'
|
||||
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
|
||||
import { db } from '@/db'
|
||||
import { chat, workflow } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('ChatSubdomainAPI')
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('Chat Edit API Route', () => {
|
||||
mockSet.mockReturnValue({ where: mockWhere })
|
||||
mockDelete.mockReturnValue({ where: mockWhere })
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
update: mockUpdate,
|
||||
@@ -38,7 +38,7 @@ describe('Chat Edit API Route', () => {
|
||||
},
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
chat: { id: 'id', subdomain: 'subdomain', userId: 'userId' },
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { chat } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -8,8 +10,6 @@ import { getEmailDomain } from '@/lib/urls/utils'
|
||||
import { encryptSecret } from '@/lib/utils'
|
||||
import { checkChatAccess } from '@/app/api/chat/utils'
|
||||
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
|
||||
import { db } from '@/db'
|
||||
import { chat } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ describe('Chat API Route', () => {
|
||||
mockInsert.mockReturnValue({ values: mockValues })
|
||||
mockValues.mockReturnValue({ returning: mockReturning })
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
insert: mockInsert,
|
||||
},
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
chat: { userId: 'userId', subdomain: 'subdomain' },
|
||||
workflow: { id: 'id', userId: 'userId', isDeployed: 'isDeployed' },
|
||||
}))
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { chat } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
@@ -9,8 +11,6 @@ import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { encryptSecret } from '@/lib/utils'
|
||||
import { checkWorkflowAccessForChatCreation } from '@/app/api/chat/utils'
|
||||
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
|
||||
import { db } from '@/db'
|
||||
import { chat } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('ChatAPI')
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@ describe('Subdomain Validation API Route', () => {
|
||||
mockWhere.mockReturnValue({ limit: mockLimit })
|
||||
|
||||
// Mock the database
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
},
|
||||
}))
|
||||
|
||||
// Mock the schema
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
chat: {
|
||||
subdomain: 'subdomain',
|
||||
},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from '@sim/db'
|
||||
import { chat } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
|
||||
import { db } from '@/db'
|
||||
import { chat } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('SubdomainValidateAPI')
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { NextResponse } from 'next/server'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { env } from '@/lib/env'
|
||||
|
||||
vi.mock('@/db', () => ({
|
||||
vi.mock('@sim/db', () => ({
|
||||
db: {
|
||||
select: vi.fn(),
|
||||
update: vi.fn(),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { chat, userStats, workflow } from '@sim/db/schema'
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
@@ -12,8 +14,6 @@ import { processStreamingBlockLogs } from '@/lib/tokenization'
|
||||
import { getEmailDomain } from '@/lib/urls/utils'
|
||||
import { decryptSecret, generateRequestId } from '@/lib/utils'
|
||||
import { getBlock } from '@/blocks'
|
||||
import { db } from '@/db'
|
||||
import { chat, userStats, workflow } from '@/db/schema'
|
||||
import { Executor } from '@/executor'
|
||||
import type { BlockLog, ExecutionResult } from '@/executor/types'
|
||||
import { Serializer } from '@/serializer'
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from '@sim/db'
|
||||
import { userStats } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkInternalApiKey } from '@/lib/copilot/utils'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { userStats } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('CopilotApiKeysValidate')
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('Copilot Chat API Route', () => {
|
||||
mockUpdate.mockReturnValue({ set: mockSet })
|
||||
mockSet.mockReturnValue({ where: mockWhere })
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
insert: mockInsert,
|
||||
@@ -54,7 +54,7 @@ describe('Copilot Chat API Route', () => {
|
||||
},
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
copilotChats: {
|
||||
id: 'id',
|
||||
userId: 'userId',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { copilotChats } from '@sim/db/schema'
|
||||
import { and, desc, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -18,8 +20,6 @@ import { generateChatTitle } from '@/lib/sim-agent/utils'
|
||||
import { createFileContent, isSupportedFileType } from '@/lib/uploads/file-utils'
|
||||
import { S3_COPILOT_CONFIG } from '@/lib/uploads/setup'
|
||||
import { downloadFile, getStorageProvider } from '@/lib/uploads/storage-client'
|
||||
import { db } from '@/db'
|
||||
import { copilotChats } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('CopilotChatAPI')
|
||||
|
||||
|
||||
@@ -32,14 +32,14 @@ describe('Copilot Chat Update Messages API Route', () => {
|
||||
mockUpdate.mockReturnValue({ set: mockSet })
|
||||
mockSet.mockReturnValue({ where: vi.fn().mockResolvedValue(undefined) }) // Different where for update
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
update: mockUpdate,
|
||||
},
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
copilotChats: {
|
||||
id: 'id',
|
||||
userId: 'userId',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { copilotChats } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -9,8 +11,6 @@ import {
|
||||
createUnauthorizedResponse,
|
||||
} from '@/lib/copilot/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { copilotChats } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('CopilotChatUpdateAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { copilotChats } from '@sim/db/schema'
|
||||
import { desc, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import {
|
||||
@@ -6,8 +8,6 @@ import {
|
||||
createUnauthorizedResponse,
|
||||
} from '@/lib/copilot/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { copilotChats } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('CopilotChatsListAPI')
|
||||
|
||||
|
||||
@@ -28,13 +28,13 @@ describe('Copilot Checkpoints Revert API Route', () => {
|
||||
mockWhere.mockReturnValue({ then: mockThen })
|
||||
mockThen.mockResolvedValue(null) // Default: no data found
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
},
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
workflowCheckpoints: {
|
||||
id: 'id',
|
||||
userId: 'userId',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { workflowCheckpoints, workflow as workflowTable } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -9,8 +11,6 @@ import {
|
||||
createUnauthorizedResponse,
|
||||
} from '@/lib/copilot/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { workflowCheckpoints, workflow as workflowTable } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('CheckpointRevertAPI')
|
||||
|
||||
|
||||
@@ -49,14 +49,14 @@ describe('Copilot Checkpoints API Route', () => {
|
||||
mockInsert.mockReturnValue({ values: mockValues })
|
||||
mockValues.mockReturnValue({ returning: mockReturning })
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
insert: mockInsert,
|
||||
},
|
||||
}))
|
||||
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
copilotChats: mockCopilotChats,
|
||||
workflowCheckpoints: mockWorkflowCheckpoints,
|
||||
}))
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { copilotChats, workflowCheckpoints } from '@sim/db/schema'
|
||||
import { and, desc, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -9,8 +11,6 @@ import {
|
||||
createUnauthorizedResponse,
|
||||
} from '@/lib/copilot/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { copilotChats, workflowCheckpoints } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('WorkflowCheckpointsAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { copilotFeedback } from '@sim/db/schema'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import {
|
||||
@@ -8,8 +10,6 @@ import {
|
||||
createUnauthorizedResponse,
|
||||
} from '@/lib/copilot/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { copilotFeedback } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('CopilotFeedbackAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { environment } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { decryptSecret, encryptSecret, generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { environment } from '@/db/schema'
|
||||
import type { EnvironmentVariable } from '@/stores/settings/environment/types'
|
||||
|
||||
const logger = createLogger('EnvironmentAPI')
|
||||
|
||||
@@ -127,7 +127,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockAuthenticatedUser()
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder Name',
|
||||
@@ -152,7 +152,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockAuthenticatedUser()
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder',
|
||||
@@ -171,7 +171,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockUnauthenticated()
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder',
|
||||
@@ -193,7 +193,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockGetUserEntityPermissions.mockResolvedValue('read') // Read-only permissions
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder',
|
||||
@@ -215,7 +215,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockGetUserEntityPermissions.mockResolvedValue('write') // Write permissions
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder',
|
||||
@@ -237,7 +237,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockGetUserEntityPermissions.mockResolvedValue('admin') // Admin permissions
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder',
|
||||
@@ -258,7 +258,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockAuthenticatedUser()
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder',
|
||||
@@ -293,7 +293,7 @@ describe('Individual Folder API Route', () => {
|
||||
}),
|
||||
})
|
||||
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: ' Folder With Spaces ',
|
||||
@@ -314,7 +314,7 @@ describe('Individual Folder API Route', () => {
|
||||
const dbMock = createFolderDbMock({
|
||||
throwError: true,
|
||||
})
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder',
|
||||
@@ -340,7 +340,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockAuthenticatedUser()
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: '', // Empty name
|
||||
@@ -359,7 +359,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockAuthenticatedUser()
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
// Create a request with invalid JSON
|
||||
const req = new Request('http://localhost:3000/api/folders/folder-1', {
|
||||
@@ -396,7 +396,7 @@ describe('Individual Folder API Route', () => {
|
||||
folderLookupResult: { id: 'folder-3', parentId: null, name: 'Folder 3' },
|
||||
circularCheckResults,
|
||||
})
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('PUT', {
|
||||
name: 'Updated Folder 3',
|
||||
@@ -425,7 +425,7 @@ describe('Individual Folder API Route', () => {
|
||||
})
|
||||
|
||||
// Mock the recursive deletion function
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('DELETE')
|
||||
const params = Promise.resolve({ id: 'folder-1' })
|
||||
@@ -445,7 +445,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockUnauthenticated()
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('DELETE')
|
||||
const params = Promise.resolve({ id: 'folder-1' })
|
||||
@@ -465,7 +465,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockGetUserEntityPermissions.mockResolvedValue('read') // Read-only permissions
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('DELETE')
|
||||
const params = Promise.resolve({ id: 'folder-1' })
|
||||
@@ -485,7 +485,7 @@ describe('Individual Folder API Route', () => {
|
||||
mockGetUserEntityPermissions.mockResolvedValue('write') // Write permissions (not enough for delete)
|
||||
|
||||
const dbMock = createFolderDbMock()
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('DELETE')
|
||||
const params = Promise.resolve({ id: 'folder-1' })
|
||||
@@ -507,7 +507,7 @@ describe('Individual Folder API Route', () => {
|
||||
const dbMock = createFolderDbMock({
|
||||
folderLookupResult: mockFolder,
|
||||
})
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('DELETE')
|
||||
const params = Promise.resolve({ id: 'folder-1' })
|
||||
@@ -528,7 +528,7 @@ describe('Individual Folder API Route', () => {
|
||||
const dbMock = createFolderDbMock({
|
||||
throwError: true,
|
||||
})
|
||||
vi.doMock('@/db', () => dbMock)
|
||||
vi.doMock('@sim/db', () => dbMock)
|
||||
|
||||
const req = createMockRequest('DELETE')
|
||||
const params = Promise.resolve({ id: 'folder-1' })
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from '@sim/db'
|
||||
import { workflow, workflowFolder } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { getUserEntityPermissions } from '@/lib/permissions/utils'
|
||||
import { db } from '@/db'
|
||||
import { workflow, workflowFolder } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('FoldersIDAPI')
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ describe('Folders API Route', () => {
|
||||
|
||||
mockGetUserEntityPermissions.mockResolvedValue('admin')
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
insert: mockInsert,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from '@sim/db'
|
||||
import { workflowFolder } from '@sim/db/schema'
|
||||
import { and, asc, desc, eq, isNull } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { getUserEntityPermissions } from '@/lib/permissions/utils'
|
||||
import { db } from '@/db'
|
||||
import { workflowFolder } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('FoldersAPI')
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ describe('Document By ID API Route', () => {
|
||||
beforeEach(async () => {
|
||||
resetMocks()
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDbChain,
|
||||
}))
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('Knowledge Base Documents API Route', () => {
|
||||
beforeEach(async () => {
|
||||
resetMocks()
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDbChain,
|
||||
}))
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ describe('Knowledge Base By ID API Route', () => {
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDbChain,
|
||||
}))
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('Knowledge Base API Route', () => {
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDbChain,
|
||||
}))
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ describe('Knowledge Search API Route', () => {
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: mockDbChain,
|
||||
}))
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ vi.mock('@/lib/logs/console/logger', () => ({
|
||||
error: vi.fn(),
|
||||
})),
|
||||
}))
|
||||
vi.mock('@/db')
|
||||
vi.mock('@sim/db')
|
||||
vi.mock('@/lib/knowledge/documents/utils', () => ({
|
||||
retryWithExponentialBackoff: (fn: any) => fn(),
|
||||
}))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { db } from '@sim/db'
|
||||
import { document, embedding } from '@sim/db/schema'
|
||||
import { and, eq, inArray, isNull, sql } from 'drizzle-orm'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { document, embedding } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('KnowledgeSearchUtils')
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ vi.stubGlobal(
|
||||
})
|
||||
)
|
||||
|
||||
vi.mock('@/db', () => {
|
||||
vi.mock('@sim/db', () => {
|
||||
const selectBuilder = {
|
||||
from(table: any) {
|
||||
return {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { db } from '@sim/db'
|
||||
import { document, embedding, knowledgeBase } from '@sim/db/schema'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import { getUserEntityPermissions } from '@/lib/permissions/utils'
|
||||
import { db } from '@/db'
|
||||
import { document, embedding, knowledgeBase } from '@/db/schema'
|
||||
|
||||
export interface KnowledgeBaseData {
|
||||
id: string
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from '@sim/db'
|
||||
import { permissions, workflow, workflowExecutionLogs } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { permissions, workflow, workflowExecutionLogs } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('LogDetailsByIdAPI')
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { PutObjectCommand } from '@aws-sdk/client-s3'
|
||||
// Dynamic import for S3 client to avoid client-side bundling
|
||||
import { db } from '@sim/db'
|
||||
import { subscription, user, workflow, workflowExecutionLogs } from '@sim/db/schema'
|
||||
import { and, eq, inArray, lt, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { verifyCronAuth } from '@/lib/auth/internal'
|
||||
@@ -6,9 +9,6 @@ import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { snapshotService } from '@/lib/logs/execution/snapshot/service'
|
||||
import { deleteFile, isUsingCloudStorage } from '@/lib/uploads'
|
||||
// Dynamic import for S3 client to avoid client-side bundling
|
||||
import { db } from '@/db'
|
||||
import { subscription, user, workflow, workflowExecutionLogs } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { db } from '@sim/db'
|
||||
import { workflowExecutionLogs, workflowExecutionSnapshots } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { workflowExecutionLogs, workflowExecutionSnapshots } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('LogsByExecutionIdAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { permissions, workflow, workflowExecutionLogs } from '@sim/db/schema'
|
||||
import { and, desc, eq, gte, inArray, lte, type SQL, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { permissions, workflow, workflowExecutionLogs } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('LogsAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { mcpServers } from '@sim/db/schema'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { withMcpAuth } from '@/lib/mcp/middleware'
|
||||
import { mcpService } from '@/lib/mcp/service'
|
||||
import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils'
|
||||
import { db } from '@/db'
|
||||
import { mcpServers } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('McpServerRefreshAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { mcpServers } from '@sim/db/schema'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
@@ -5,8 +7,6 @@ import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware'
|
||||
import { mcpService } from '@/lib/mcp/service'
|
||||
import { validateMcpServerUrl } from '@/lib/mcp/url-validator'
|
||||
import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils'
|
||||
import { db } from '@/db'
|
||||
import { mcpServers } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('McpServerAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { mcpServers } from '@sim/db/schema'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
@@ -6,8 +8,6 @@ import { mcpService } from '@/lib/mcp/service'
|
||||
import type { McpTransport } from '@/lib/mcp/types'
|
||||
import { validateMcpServerUrl } from '@/lib/mcp/url-validator'
|
||||
import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils'
|
||||
import { db } from '@/db'
|
||||
import { mcpServers } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('McpServersAPI')
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from '@sim/db'
|
||||
import { memory } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { memory } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('MemoryByIdAPI')
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from '@sim/db'
|
||||
import { memory } from '@sim/db/schema'
|
||||
import { and, eq, isNull, like } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { memory } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('MemoryAPI')
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { db } from '@sim/db'
|
||||
import {
|
||||
invitation,
|
||||
member,
|
||||
@@ -12,7 +8,11 @@ import {
|
||||
user,
|
||||
type WorkspaceInvitationStatus,
|
||||
workspaceInvitation,
|
||||
} from '@/db/schema'
|
||||
} from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
|
||||
const logger = createLogger('OrganizationInvitation')
|
||||
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import {
|
||||
invitation,
|
||||
member,
|
||||
organization,
|
||||
user,
|
||||
type WorkspaceInvitationStatus,
|
||||
workspace,
|
||||
workspaceInvitation,
|
||||
} from '@sim/db/schema'
|
||||
import { and, eq, inArray, isNull } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import {
|
||||
@@ -16,16 +26,6 @@ import { quickValidateEmail } from '@/lib/email/validation'
|
||||
import { env } from '@/lib/env'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { hasWorkspaceAdminAccess } from '@/lib/permissions/utils'
|
||||
import { db } from '@/db'
|
||||
import {
|
||||
invitation,
|
||||
member,
|
||||
organization,
|
||||
user,
|
||||
type WorkspaceInvitationStatus,
|
||||
workspace,
|
||||
workspaceInvitation,
|
||||
} from '@/db/schema'
|
||||
|
||||
const logger = createLogger('OrganizationInvitations')
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from '@sim/db'
|
||||
import { member, user, userStats } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { getUserUsageData } from '@/lib/billing/core/usage'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { member, user, userStats } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('OrganizationMemberAPI')
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { invitation, member, organization, user, userStats } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getEmailSubject, renderInvitationEmail } from '@/components/emails/render-email'
|
||||
@@ -9,8 +11,6 @@ import { sendEmail } from '@/lib/email/mailer'
|
||||
import { quickValidateEmail } from '@/lib/email/validation'
|
||||
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'
|
||||
|
||||
const logger = createLogger('OrganizationMembersAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { member, organization } from '@sim/db/schema'
|
||||
import { and, eq, ne } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
@@ -7,8 +9,6 @@ import {
|
||||
updateOrganizationSeats,
|
||||
} from '@/lib/billing/validation/seat-management'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { member, organization } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('OrganizationAPI')
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from '@sim/db'
|
||||
import { member, permissions, user, workspace } from '@sim/db/schema'
|
||||
import { and, eq, or } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { db } from '@/db'
|
||||
import { member, permissions, user, workspace } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('OrganizationWorkspacesAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { workflow, workflowSchedule } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { getUserEntityPermissions } from '@/lib/permissions/utils'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { workflow, workflowSchedule } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('ScheduleAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { workflow, workflowSchedule } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { getUserEntityPermissions } from '@/lib/permissions/utils'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { workflow, workflowSchedule } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('ScheduleStatusAPI')
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('Scheduled Workflow Execution API Route', () => {
|
||||
})),
|
||||
}))
|
||||
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
const mockDb = {
|
||||
select: vi.fn().mockImplementation(() => ({
|
||||
from: vi.fn().mockImplementation((table: string) => {
|
||||
@@ -147,7 +147,7 @@ describe('Scheduled Workflow Execution API Route', () => {
|
||||
})
|
||||
|
||||
it('should handle case with no due schedules', async () => {
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
const mockDb = {
|
||||
select: vi.fn().mockImplementation(() => ({
|
||||
from: vi.fn().mockImplementation(() => ({
|
||||
@@ -183,7 +183,7 @@ describe('Scheduled Workflow Execution API Route', () => {
|
||||
})
|
||||
|
||||
it('should handle scheduler-level errors gracefully', async () => {
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
const mockDb = {
|
||||
select: vi.fn().mockImplementation(() => {
|
||||
throw new Error('Database error')
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { userStats, workflow, workflowSchedule } from '@sim/db/schema'
|
||||
import { Cron } from 'croner'
|
||||
import { and, eq, lte, not, sql } from 'drizzle-orm'
|
||||
import { NextResponse } from 'next/server'
|
||||
@@ -18,8 +20,6 @@ import {
|
||||
import { decryptSecret, generateRequestId } from '@/lib/utils'
|
||||
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/db-helpers'
|
||||
import { updateWorkflowRunCounts } from '@/lib/workflows/utils'
|
||||
import { db } from '@/db'
|
||||
import { userStats, workflow, workflowSchedule } from '@/db/schema'
|
||||
import { Executor } from '@/executor'
|
||||
import { Serializer } from '@/serializer'
|
||||
import { RateLimiter } from '@/services/queue'
|
||||
|
||||
@@ -52,7 +52,7 @@ describe('Schedule Configuration API Route', () => {
|
||||
|
||||
// Create mock database with test schedules
|
||||
// Mock the database to return workflow data for authorization check
|
||||
vi.doMock('@/db', () => {
|
||||
vi.doMock('@sim/db', () => {
|
||||
let callCount = 0
|
||||
const mockDb = {
|
||||
select: vi.fn().mockImplementation(() => ({
|
||||
@@ -201,7 +201,7 @@ describe('Schedule Configuration API Route', () => {
|
||||
where: vi.fn().mockResolvedValue([]),
|
||||
}))
|
||||
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: vi.fn().mockImplementation(() => ({
|
||||
from: vi.fn().mockImplementation(() => ({
|
||||
@@ -271,7 +271,7 @@ describe('Schedule Configuration API Route', () => {
|
||||
*/
|
||||
it('should handle errors gracefully', async () => {
|
||||
// Mock the db to throw an error on insert
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: vi.fn().mockImplementation(() => ({
|
||||
from: vi.fn().mockImplementation(() => ({
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { workflow, workflowSchedule } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -13,8 +15,6 @@ import {
|
||||
validateCronExpression,
|
||||
} from '@/lib/schedules/utils'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { workflow, workflowSchedule } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('ScheduledAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { templates, workflow } from '@sim/db/schema'
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -5,8 +7,6 @@ import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { hasAdminPermission } from '@/lib/permissions/utils'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { templates, workflow } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('TemplateByIdAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { templateStars, templates } from '@sim/db/schema'
|
||||
import { and, eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { templateStars, templates } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('TemplateStarAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { templates, workflow, workflowBlocks, workflowEdges } from '@sim/db/schema'
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { templates, workflow, workflowBlocks, workflowEdges } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('TemplateUseAPI')
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { templateStars, templates, workflow } from '@sim/db/schema'
|
||||
import { and, desc, eq, ilike, or, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
@@ -5,8 +7,6 @@ import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { db } from '@/db'
|
||||
import { templateStars, templates, workflow } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('TemplatesAPI')
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('Custom Tools API Routes', () => {
|
||||
mockDelete.mockReturnValue({ where: mockWhere })
|
||||
|
||||
// Mock database
|
||||
vi.doMock('@/db', () => ({
|
||||
vi.doMock('@sim/db', () => ({
|
||||
db: {
|
||||
select: mockSelect,
|
||||
insert: mockInsert,
|
||||
@@ -110,7 +110,7 @@ describe('Custom Tools API Routes', () => {
|
||||
}))
|
||||
|
||||
// Mock schema
|
||||
vi.doMock('@/db/schema', () => ({
|
||||
vi.doMock('@sim/db/schema', () => ({
|
||||
customTools: {
|
||||
userId: 'userId', // Add these properties to enable WHERE clauses with eq()
|
||||
id: 'id',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { db } from '@sim/db'
|
||||
import { customTools } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
@@ -5,8 +7,6 @@ import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { getUserId } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { customTools } from '@/db/schema'
|
||||
|
||||
const logger = createLogger('CustomToolsAPI')
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
const logger = createLogger('GmailLabelsAPI')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
import type { PlannerTask } from '@/tools/microsoft_planner/types'
|
||||
|
||||
const logger = createLogger('MicrosoftPlannerTasksAPI')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { db } from '@/db'
|
||||
import { account } from '@/db/schema'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user