Compare commits

...

14 Commits

Author SHA1 Message Date
Waleed Latif
9c12ddf491 v0.3.14: aliased imports, logger naming changes, teams webhook synchronization 2025-07-28 10:05:07 -07:00
Vikhyath Mondreti
27ef45f717 no immediate acks for ms teams webhook (#805) 2025-07-28 09:21:59 -07:00
Waleed Latif
0414aa5f6d refactor(imports): added aliased imports everywhere (#799)
* refactor(imports): added aliased imports everywhere

* more aliased imports

* add barrel exports

* add more barrel exports

* cleanup

---------

Co-authored-by: waleedlatif <waleedlatif@waleedlatifs-MacBook-Pro.local>
2025-07-26 16:10:32 -07:00
Waleed Latif
93f68a9092 refactor(logger): code cleanup for new execution logger (#798)
* refactor(logger): code hygiene with new logger

* modify remaining files

* simplify code structure

---------

Co-authored-by: waleedlatif <waleedlatif@waleedlatifs-MacBook-Pro.local>
2025-07-26 15:05:33 -07:00
Waleed Latif
727e5e8763 feat(workflow): added cancellation after launching manual execution (#796)
* feat(worfklow): added cancellation after launching manual execution

* fix build error

* ack PR comments

---------

Co-authored-by: waleedlatif <waleedlatif@waleedlatifs-MacBook-Pro.local>
2025-07-26 12:54:08 -07:00
Waleed Latif
4964495abb fix(picker): fix docs.google.com refused to connect issue (#797)
Co-authored-by: waleedlatif <waleedlatif@waleedlatifs-MacBook-Pro.local>
2025-07-26 12:45:44 -07:00
Vikhyath Mondreti
40d3ce5e10 v0.3.13: fix create-manifest job 2025-07-25 16:22:48 -07:00
Vikhyath Mondreti
a251122601 fix(create-manifest): manifest not using right tags by arch (#793)
* fix create manifest to pick out right tags

* fix
2025-07-25 16:20:53 -07:00
Vikhyath Mondreti
9e8d2f7c7d Merge pull request #792 from simstudioai/staging
v0.3.11: arm64 runner, CDN video support
2025-07-25 16:02:59 -07:00
Vikhyath Mondreti
eeb1a340b2 feat: implement native ARM64 Docker builds with CDN support (#791)
* feat: implement native ARM64 Docker builds with CDN support

- Replace QEMU emulation with native ARM64/AMD64 runners (linux-arm64-8-core, linux-x64-8-core)
- Fix manifest creation with proper error handling and image existence checks
- Add CDN video support with getVideoUrl function and Video component
- Update all docs MDX files to use Video component instead of raw video tags
- Update GitHub Actions workflow to use architecture-specific builds
- Remove QEMU setup to eliminate emulation timeout issues
- Maintain multi-arch Docker image support through manifests

* Update .github/workflows/build.yml

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2025-07-25 15:57:16 -07:00
Vikhyath Mondreti
c91c132e88 Merge pull request #789 from simstudioai/staging
v0.3.11: fix force-dynamic routes, webhooks, kb search perms
2025-07-25 12:44:19 -07:00
Vikhyath Mondreti
5028930b9f fix(webhooks): immediate acks only for teams (#788) 2025-07-25 11:05:14 -07:00
Vikhyath Mondreti
b565babe1f fix(nextjs): add force dynamic to 38 routes (#787) 2025-07-25 10:29:47 -07:00
Vikhyath Mondreti
2f57d8a884 fix(kb-perms): search tool perms to use new system (#786)
* fix(kb): search tool perms

* fix tests
2025-07-24 20:44:26 -07:00
663 changed files with 3226 additions and 2190 deletions

View File

@@ -7,17 +7,43 @@ on:
jobs:
build-and-push:
runs-on: ubuntu-latest-8-cores
strategy:
fail-fast: false
matrix:
include:
# AMD64 builds on x86 runners
- dockerfile: ./docker/app.Dockerfile
image: ghcr.io/simstudioai/simstudio
platform: linux/amd64
arch: amd64
runner: linux-x64-8-core
- dockerfile: ./docker/db.Dockerfile
image: ghcr.io/simstudioai/migrations
platform: linux/amd64
arch: amd64
runner: linux-x64-8-core
- dockerfile: ./docker/realtime.Dockerfile
image: ghcr.io/simstudioai/realtime
platform: linux/amd64
arch: amd64
runner: linux-x64-8-core
# ARM64 builds on native ARM64 runners
- dockerfile: ./docker/app.Dockerfile
image: ghcr.io/simstudioai/simstudio
platform: linux/arm64
arch: arm64
runner: linux-arm64-8-core
- dockerfile: ./docker/db.Dockerfile
image: ghcr.io/simstudioai/migrations
platform: linux/arm64
arch: arm64
runner: linux-arm64-8-core
- dockerfile: ./docker/realtime.Dockerfile
image: ghcr.io/simstudioai/realtime
platform: linux/arm64
arch: arm64
runner: linux-arm64-8-core
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
@@ -26,9 +52,6 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -41,6 +64,55 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ matrix.image }}
tags: |
type=raw,value=latest-${{ matrix.arch }},enable=${{ github.ref == 'refs/heads/main' }}
type=ref,event=pr,suffix=-${{ matrix.arch }}
type=semver,pattern={{version}},suffix=-${{ matrix.arch }}
type=semver,pattern={{major}}.{{minor}},suffix=-${{ matrix.arch }}
type=semver,pattern={{major}}.{{minor}}.{{patch}},suffix=-${{ matrix.arch }}
type=sha,format=long,suffix=-${{ matrix.arch }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ${{ matrix.dockerfile }}
platforms: ${{ matrix.platform }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=build-v2
cache-to: type=gha,mode=max,scope=build-v2
provenance: false
sbom: false
create-manifests:
runs-on: ubuntu-latest
needs: build-and-push
if: github.event_name != 'pull_request'
strategy:
matrix:
include:
- image: ghcr.io/simstudioai/simstudio
- image: ghcr.io/simstudioai/migrations
- image: ghcr.io/simstudioai/realtime
permissions:
contents: read
packages: write
steps:
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for manifest
id: meta
uses: docker/metadata-action@v5
with:
@@ -53,14 +125,35 @@ jobs:
type=semver,pattern={{major}}.{{minor}}.{{patch}}
type=sha,format=long
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ${{ matrix.dockerfile }}
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Create and push manifest
run: |
# Extract the tags from metadata (these are the final manifest tags we want)
MANIFEST_TAGS="${{ steps.meta.outputs.tags }}"
# Create manifest for each tag
for manifest_tag in $MANIFEST_TAGS; do
echo "Creating manifest for $manifest_tag"
# The architecture-specific images have -amd64 and -arm64 suffixes
amd64_image="${manifest_tag}-amd64"
arm64_image="${manifest_tag}-arm64"
echo "Looking for images: $amd64_image and $arm64_image"
# Check if both architecture images exist
if docker manifest inspect "$amd64_image" >/dev/null 2>&1 && docker manifest inspect "$arm64_image" >/dev/null 2>&1; then
echo "Both images found, creating manifest..."
docker manifest create "$manifest_tag" \
"$amd64_image" \
"$arm64_image"
docker manifest push "$manifest_tag"
echo "Successfully created and pushed manifest for $manifest_tag"
else
echo "Error: One or both architecture images not found"
echo "Checking AMD64 image: $amd64_image"
docker manifest inspect "$amd64_image" || echo "AMD64 image not found"
echo "Checking ARM64 image: $arm64_image"
docker manifest inspect "$arm64_image" || echo "ARM64 image not found"
exit 1
fi
done

View File

@@ -1,4 +1,3 @@
import { cn } from '@/lib/utils'
import {
AgentIcon,
ApiIcon,
@@ -7,7 +6,8 @@ import {
ConditionalIcon,
ConnectIcon,
ResponseIcon,
} from '../icons'
} from '@/components/icons'
import { cn } from '@/lib/utils'
// Custom Feature component specifically for BlockTypes to handle the 6-item layout
const BlockFeature = ({

View File

@@ -0,0 +1,30 @@
import { getVideoUrl } from '@/lib/utils'
interface VideoProps {
src: string
className?: string
autoPlay?: boolean
loop?: boolean
muted?: boolean
playsInline?: boolean
}
export function Video({
src,
className = 'w-full -mb-2 rounded-lg',
autoPlay = true,
loop = true,
muted = true,
playsInline = true,
}: VideoProps) {
return (
<video
autoPlay={autoPlay}
loop={loop}
muted={muted}
playsInline={playsInline}
className={className}
src={getVideoUrl(src)}
/>
)
}

View File

@@ -7,6 +7,7 @@ import { Callout } from 'fumadocs-ui/components/callout'
import { Step, Steps } from 'fumadocs-ui/components/steps'
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
import { ThemeImage } from '@/components/ui/theme-image'
import { Video } from '@/components/ui/video'
The Evaluator block uses AI to score and assess content quality based on metrics you define. Perfect for quality control, A/B testing, and ensuring your AI outputs meet specific standards.
@@ -63,7 +64,7 @@ Choose an AI model to perform the evaluation:
**Local Models**: Any model running on Ollama
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/models.mp4"></video>
<Video src="models.mp4" />
</div>
**Recommendation**: Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for more accurate evaluations.

View File

@@ -7,11 +7,12 @@ import { Card, Cards } from 'fumadocs-ui/components/card'
import { Step, Steps } from 'fumadocs-ui/components/steps'
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
import { BlockTypes } from '@/components/ui/block-types'
import { Video } from '@/components/ui/video'
Blocks are the building components you connect together to create AI workflows. Think of them as specialized modules that each handle a specific task—from chatting with AI models to making API calls or processing data.
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
<Video src="connections.mp4" />
</div>
## Core Block Types
@@ -62,7 +63,7 @@ You create workflows by connecting blocks together. The output of one block beco
- **Branching paths**: Some blocks can route to different paths based on conditions
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
<Video src="connections.mp4" />
</div>
## Common Patterns

View File

@@ -8,6 +8,7 @@ import { Step, Steps } from 'fumadocs-ui/components/steps'
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'
import { ThemeImage } from '@/components/ui/theme-image'
import { Video } from '@/components/ui/video'
The Router block uses AI to intelligently decide which path your workflow should take next. Unlike Condition blocks that use simple rules, Router blocks can understand context and make smart routing decisions based on content analysis.
@@ -103,7 +104,7 @@ Choose an AI model to power the routing decision:
**Local Models**: Any model running on Ollama
<div className="w-full max-w-2xl mx-auto overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/router-model-dropdown.mp4"></video>
<Video src="router-model-dropdown.mp4" />
</div>
**Recommendation**: Use models with strong reasoning capabilities like GPT-4o or Claude 3.7 Sonnet for more accurate routing decisions.

View File

@@ -6,6 +6,7 @@ description: Connect your blocks to one another.
import { Callout } from 'fumadocs-ui/components/callout'
import { Card, Cards } from 'fumadocs-ui/components/card'
import { ConnectIcon } from '@/components/icons'
import { Video } from '@/components/ui/video'
Connections are the pathways that allow data to flow between blocks in your workflow. They define how information is passed from one block to another, enabling you to create sophisticated, multi-step processes.
@@ -15,7 +16,7 @@ Connections are the pathways that allow data to flow between blocks in your work
</Callout>
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
<Video src="connections.mp4" />
</div>
## Connection Types

View File

@@ -4,11 +4,12 @@ description: Using connection tags to reference data between blocks
---
import { Callout } from 'fumadocs-ui/components/callout'
import { Video } from '@/components/ui/video'
Connection tags are visual representations of the data available from connected blocks. They provide an easy way to reference outputs from previous blocks in your workflow.
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/connections.mp4"></video>
<Video src="connections.mp4" />
</div>
### What Are Connection Tags?

View File

@@ -20,6 +20,7 @@ import {
LoopIcon,
ParallelIcon,
} from '@/components/icons'
import { Video } from '@/components/ui/video'
When you run a workflow in Sim Studio, the execution engine follows a systematic process to ensure blocks are executed in the correct order with proper data flow.
@@ -162,7 +163,7 @@ Run workflows on-demand through the Sim Studio interface by clicking the "Run" b
- Workflows that need human supervision
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/input-format.mp4"></video>
<Video src="input-format.mp4" />
</div>
### Scheduled Execution
@@ -175,7 +176,7 @@ Configure workflows to run automatically on a specified schedule:
- Set minimum and maximum execution intervals
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/configure-schedule.mp4"></video>
<Video src="configure-schedule.mp4" />
</div>
### API Endpoints
@@ -188,7 +189,7 @@ Each workflow can be exposed as an API endpoint:
- Receive execution results as JSON responses
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/api-deployment.mp4"></video>
<Video src="api-deployment.mp4" />
</div>
#### Viewing Deployed APIs
@@ -196,7 +197,7 @@ Each workflow can be exposed as an API endpoint:
Monitor your deployed workflow APIs and their current state:
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/api-redeployment.mp4"></video>
<Video src="api-redeployment.mp4" />
</div>
This shows how to view the deployed state and compare with the original deployed API configuration.
@@ -211,7 +212,7 @@ Configure workflows to execute in response to external events:
- Support for specialized webhooks (GitHub, Stripe, etc.)
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/webhooks.mp4"></video>
<Video src="webhooks.mp4" />
</div>
<Callout type="info">

View File

@@ -23,6 +23,7 @@ import {
PerplexityIcon,
SlackIcon,
} from '@/components/icons'
import { Video } from '@/components/ui/video'
This tutorial will guide you through building your first AI workflow in Sim Studio. We'll create a people research agent that can find information about individuals using state-of-the-art LLM-Search tools.
@@ -63,7 +64,7 @@ A people research agent that:
- **User Prompt**: Drag the connection from the Start block's output into this field (this connects `<start.input>` to the user prompt)
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-2.mp4"></video>
<Video src="examples/started-2.mp4" />
</div>
</Step>
@@ -77,7 +78,7 @@ A people research agent that:
- Add your API keys for both tools (this allows the agent to search the web and access additional information)
<div className="mx-auto w-3/5 overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-3.mp4"></video>
<Video src="examples/started-3.mp4" />
</div>
</Step>
@@ -92,7 +93,7 @@ A people research agent that:
You should see the agent's response analyzing the person described in your text.
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-4.mp4"></video>
<Video src="examples/started-4.mp4" />
</div>
</Step>
@@ -105,7 +106,7 @@ A people research agent that:
- The AI will generate a JSON schema for you automatically
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-5.mp4"></video>
<Video src="examples/started-5.mp4" />
</div>
</Step>
@@ -120,7 +121,7 @@ A people research agent that:
You should now see structured JSON output with the person's information organized into location, profession, and education fields.
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/static/examples/started/started-6.mp4"></video>
<Video src="examples/started-6.mp4" />
</div>
</Step>
</Steps>

View File

@@ -6,11 +6,12 @@ description: Trigger workflow execution from external webhooks
import { Callout } from 'fumadocs-ui/components/callout'
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
import { ThemeImage } from '@/components/ui/theme-image'
import { Video } from '@/components/ui/video'
The Webhook block allows external services to automatically trigger your workflow execution through HTTP webhooks.
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/webhooks.mp4"></video>
<Video src="webhooks.mp4" />
</div>
## Supported Providers

View File

@@ -7,11 +7,12 @@ import { Callout } from 'fumadocs-ui/components/callout'
import { Step, Steps } from 'fumadocs-ui/components/steps'
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
import { ThemeImage } from '@/components/ui/theme-image'
import { Video } from '@/components/ui/video'
Variables in Sim Studio act as a global store for data that can be accessed and modified by any block in your workflow. They provide a powerful way to share information between different parts of your workflow, maintain state, and create more dynamic applications.
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/variables.mp4"></video>
<Video src="variables.mp4" />
</div>
<Callout type="info">
@@ -57,7 +58,7 @@ Variables can be accessed from any block in your workflow using the variable dro
3. Select the variable you want to use
<div className="mx-auto w-full overflow-hidden rounded-lg">
<video autoPlay loop muted playsInline className="w-full -mb-2 rounded-lg" src="/variables-dropdown.mp4"></video>
<Video src="variables-dropdown.mp4" />
</div>
<Callout>

View File

@@ -7,3 +7,15 @@ import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
/**
* Get the full URL for a video asset stored in Vercel Blob
*/
export function getVideoUrl(filename: string) {
const baseUrl = process.env.NEXT_PUBLIC_BLOB_BASE_URL
if (!baseUrl) {
console.warn('NEXT_PUBLIC_BLOB_BASE_URL not configured, falling back to local path')
return `/${filename}`
}
return `${baseUrl}/${filename}`
}

View File

@@ -2,7 +2,7 @@
import Image from 'next/image'
import Link from 'next/link'
import { GridPattern } from '../(landing)/components/grid-pattern'
import { GridPattern } from '@/app/(landing)/components/grid-pattern'
export default function AuthLayout({ children }: { children: React.ReactNode }) {
return (

View File

@@ -6,7 +6,7 @@ import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { useRouter, useSearchParams } from 'next/navigation'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { client } from '@/lib/auth-client'
import LoginPage from './login-form'
import LoginPage from '@/app/(auth)/login/login-form'
vi.mock('next/navigation', () => ({
useRouter: vi.fn(),

View File

@@ -15,7 +15,7 @@ import {
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { client } from '@/lib/auth-client'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { cn } from '@/lib/utils'
import { SocialLoginButtons } from '@/app/(auth)/components/social-login-buttons'

View File

@@ -1,5 +1,5 @@
import { getOAuthProviderStatus } from '../components/oauth-provider-checker'
import LoginForm from './login-form'
import { getOAuthProviderStatus } from '@/app/(auth)/components/oauth-provider-checker'
import LoginForm from '@/app/(auth)/login/login-form'
// Force dynamic rendering to avoid prerender errors with search params
export const dynamic = 'force-dynamic'

View File

@@ -11,8 +11,8 @@ import {
CardHeader,
CardTitle,
} from '@/components/ui/card'
import { createLogger } from '@/lib/logs/console-logger'
import { SetNewPasswordForm } from './reset-password-form'
import { createLogger } from '@/lib/logs/console/logger'
import { SetNewPasswordForm } from '@/app/(auth)/reset-password/reset-password-form'
const logger = createLogger('ResetPasswordPage')

View File

@@ -1,6 +1,6 @@
import { env, isTruthy } from '@/lib/env'
import { getOAuthProviderStatus } from '../components/oauth-provider-checker'
import SignupForm from './signup-form'
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'

View File

@@ -6,7 +6,7 @@ import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { useRouter, useSearchParams } from 'next/navigation'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { client } from '@/lib/auth-client'
import SignupPage from './signup-form'
import SignupPage from '@/app/(auth)/signup/signup-form'
vi.mock('next/navigation', () => ({
useRouter: vi.fn(),

View File

@@ -1,7 +1,7 @@
import { env } from '@/lib/env'
import { isProd } from '@/lib/environment'
import { getBaseUrl } from '@/lib/urls/utils'
import { VerifyContent } from './verify-content'
import { VerifyContent } from '@/app/(auth)/verify/verify-content'
// Force dynamic rendering to avoid prerender errors with search params
export const dynamic = 'force-dynamic'

View File

@@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import { client } from '@/lib/auth-client'
import { env, isTruthy } from '@/lib/env'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('useVerification')

View File

@@ -4,7 +4,7 @@ import { Suspense, useEffect, useState } from 'react'
import { Button } from '@/components/ui/button'
import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp'
import { cn } from '@/lib/utils'
import { useVerification } from './use-verification'
import { useVerification } from '@/app/(auth)/verify/use-verification'
interface VerifyContentProps {
hasResendKey: boolean

View File

@@ -17,9 +17,9 @@ import ReactFlow, {
} from 'reactflow'
import 'reactflow/dist/style.css'
import { HeroBlock } from './hero-block'
import { HeroEdge } from './hero-edge'
import { useWindowSize } from './use-window-size'
import { HeroBlock } from '@/app/(landing)/components/hero-block'
import { HeroEdge } from '@/app/(landing)/components/hero-edge'
import { useWindowSize } from '@/app/(landing)/components/use-window-size'
const nodeTypes: NodeTypes = { heroBlock: HeroBlock }
const edgeTypes: EdgeTypes = { heroEdge: HeroEdge }

View File

@@ -15,7 +15,7 @@ import {
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet'
import { usePrefetchOnHover } from '../utils/prefetch'
import { usePrefetchOnHover } from '@/app/(landing)/utils/prefetch'
// --- Framer Motion Variants ---
const desktopNavContainerVariants = {

View File

@@ -3,9 +3,9 @@
import { useEffect, useState } from 'react'
import { AnimatePresence, motion } from 'framer-motion'
import { usePathname } from 'next/navigation'
import { getFormattedGitHubStars } from '../actions/github'
import GitHubStarsClient from './github-stars-client'
import NavClient from './nav-client'
import { getFormattedGitHubStars } from '@/app/(landing)/actions/github'
import GitHubStarsClient from '@/app/(landing)/components/github-stars-client'
import NavClient from '@/app/(landing)/components/nav-client'
interface NavWrapperProps {
onOpenTypeformLink: () => void

View File

@@ -1,7 +1,7 @@
'use client'
import { motion } from 'framer-motion'
import { BlogCard } from '../blog-card'
import { BlogCard } from '@/app/(landing)/components/blog-card'
function Blogs() {
return (

View File

@@ -18,8 +18,8 @@ import 'reactflow/dist/style.css'
import { AgentIcon, ConnectIcon, StartIcon } from '@/components/icons'
import { cn } from '@/lib/utils'
import { DotPattern } from '../dot-pattern'
import { HeroBlock } from '../hero-block'
import { DotPattern } from '@/app/(landing)/components/dot-pattern'
import { HeroBlock } from '@/app/(landing)/components/hero-block'
// --- Types ---
type Feature = {

View File

@@ -6,8 +6,8 @@ import { useRouter } from 'next/navigation'
import { DiscordIcon, GithubIcon, xIcon as XIcon } from '@/components/icons'
import { Button } from '@/components/ui/button'
import { useSession } from '@/lib/auth-client'
import { usePrefetchOnHover } from '../../utils/prefetch'
import useIsMobile from '../hooks/use-is-mobile'
import useIsMobile from '@/app/(landing)/components/hooks/use-is-mobile'
import { usePrefetchOnHover } from '@/app/(landing)/utils/prefetch'
function Footer() {
const router = useRouter()

View File

@@ -5,8 +5,8 @@ import { Command, CornerDownLeft } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { Button } from '@/components/ui/button'
import { useSession } from '@/lib/auth-client'
import { GridPattern } from '../grid-pattern'
import HeroWorkflowProvider from '../hero-workflow'
import { GridPattern } from '@/app/(landing)/components/grid-pattern'
import HeroWorkflowProvider from '@/app/(landing)/components/hero-workflow'
function Hero() {
const router = useRouter()

View File

@@ -3,9 +3,9 @@
import { motion } from 'framer-motion'
import { GitBranch, RefreshCcw } from 'lucide-react'
import ReactFlow, { ConnectionLineType, Position, ReactFlowProvider } from 'reactflow'
import { DotPattern } from '@/app/(landing)/components/dot-pattern'
import { HeroBlock } from '@/app/(landing)/components/hero-block'
import { OrbitingCircles } from '@/app/(landing)/components/magicui/orbiting-circles'
import { DotPattern } from '../dot-pattern'
import { HeroBlock } from '../hero-block'
function Integrations() {
return (

View File

@@ -1,8 +1,8 @@
'use client'
import { motion } from 'framer-motion'
import useIsMobile from '@/app/(landing)/components/hooks/use-is-mobile'
import { Marquee } from '@/app/(landing)/components/magicui/marquee'
import useIsMobile from '../hooks/use-is-mobile'
const X_TESTIMONIALS = [
{

View File

@@ -26,10 +26,10 @@ import {
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { GridPattern } from '../components/grid-pattern'
import NavWrapper from '../components/nav-wrapper'
import Footer from '../components/sections/footer'
import { getCachedContributorsData, prefetchContributorsData } from '../utils/prefetch'
import { GridPattern } from '@/app/(landing)/components/grid-pattern'
import NavWrapper from '@/app/(landing)/components/nav-wrapper'
import Footer from '@/app/(landing)/components/sections/footer'
import { getCachedContributorsData, prefetchContributorsData } from '@/app/(landing)/utils/prefetch'
interface Contributor {
login: string

View File

@@ -1,10 +1,10 @@
'use client'
import NavWrapper from './components/nav-wrapper'
import Footer from './components/sections/footer'
import Hero from './components/sections/hero'
import Integrations from './components/sections/integrations'
import Testimonials from './components/sections/testimonials'
import NavWrapper from '@/app/(landing)/components/nav-wrapper'
import Footer from '@/app/(landing)/components/sections/footer'
import Hero from '@/app/(landing)/components/sections/hero'
import Integrations from '@/app/(landing)/components/sections/integrations'
import Testimonials from '@/app/(landing)/components/sections/testimonials'
export default function Landing() {
const handleOpenTypeformLink = () => {

View File

@@ -1,9 +1,9 @@
'use client'
import Link from 'next/link'
import { GridPattern } from '../components/grid-pattern'
import NavWrapper from '../components/nav-wrapper'
import Footer from '../components/sections/footer'
import { GridPattern } from '@/app/(landing)/components/grid-pattern'
import NavWrapper from '@/app/(landing)/components/nav-wrapper'
import Footer from '@/app/(landing)/components/sections/footer'
export default function PrivacyPolicy() {
const handleOpenTypeformLink = () => {

View File

@@ -1,9 +1,9 @@
'use client'
import Link from 'next/link'
import { GridPattern } from '../components/grid-pattern'
import NavWrapper from '../components/nav-wrapper'
import Footer from '../components/sections/footer'
import { GridPattern } from '@/app/(landing)/components/grid-pattern'
import NavWrapper from '@/app/(landing)/components/nav-wrapper'
import Footer from '@/app/(landing)/components/sections/footer'
export default function TermsOfService() {
const handleOpenTypeformLink = () => {

View File

@@ -1,6 +1,6 @@
// Utility for prefetching and caching contributors page data
import { getCommitsData, getContributors, getRepositoryStats } from '../actions/github'
import { generateActivityData, generateCommitTimelineData } from './github'
import { getCommitsData, getContributors, getRepositoryStats } from '@/app/(landing)/actions/github'
import { generateActivityData, generateCommitTimelineData } from '@/app/(landing)/utils/github'
interface Contributor {
login: string

View File

@@ -279,7 +279,7 @@ export function mockExecutionDependencies() {
}
})
vi.mock('@/lib/logs/trace-spans', () => ({
vi.mock('@/lib/logs/execution/trace-spans/trace-spans', () => ({
buildTraceSpans: vi.fn().mockReturnValue({
traceSpans: [],
totalDuration: 100,
@@ -375,7 +375,7 @@ export function mockWorkflowAccessValidation(shouldSucceed = true) {
export async function getMockedDependencies() {
const utilsModule = await import('@/lib/utils')
const traceSpansModule = await import('@/lib/logs/trace-spans')
const traceSpansModule = await import('@/lib/logs/execution/trace-spans/trace-spans')
const workflowUtilsModule = await import('@/lib/workflows/utils')
const executorModule = await import('@/executor')
const serializerModule = await import('@/serializer')
@@ -655,7 +655,7 @@ export function mockKnowledgeSchemas() {
* Mock console logger
*/
export function mockConsoleLogger() {
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
}

View File

@@ -27,7 +27,7 @@ describe('Forget Password API Route', () => {
redirectTo: 'https://example.com/reset',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/forget-password/route')
const response = await POST(req)
const data = await response.json()
@@ -56,7 +56,7 @@ describe('Forget Password API Route', () => {
email: 'test@example.com',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/forget-password/route')
const response = await POST(req)
const data = await response.json()
@@ -79,7 +79,7 @@ describe('Forget Password API Route', () => {
const req = createMockRequest('POST', {})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/forget-password/route')
const response = await POST(req)
const data = await response.json()
@@ -98,7 +98,7 @@ describe('Forget Password API Route', () => {
email: '',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/forget-password/route')
const response = await POST(req)
const data = await response.json()
@@ -126,7 +126,7 @@ describe('Forget Password API Route', () => {
email: 'nonexistent@example.com',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/forget-password/route')
const response = await POST(req)
const data = await response.json()
@@ -134,7 +134,7 @@ describe('Forget Password API Route', () => {
expect(response.status).toBe(500)
expect(data.message).toBe(errorMessage)
const logger = await import('@/lib/logs/console-logger')
const logger = await import('@/lib/logs/console/logger')
const mockLogger = logger.createLogger('ForgetPasswordTest')
expect(mockLogger.error).toHaveBeenCalledWith('Error requesting password reset:', {
error: expect.any(Error),
@@ -156,7 +156,7 @@ describe('Forget Password API Route', () => {
email: 'test@example.com',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/forget-password/route')
const response = await POST(req)
const data = await response.json()
@@ -164,7 +164,7 @@ describe('Forget Password API Route', () => {
expect(response.status).toBe(500)
expect(data.message).toBe('Failed to send password reset email. Please try again later.')
const logger = await import('@/lib/logs/console-logger')
const logger = await import('@/lib/logs/console/logger')
const mockLogger = logger.createLogger('ForgetPasswordTest')
expect(mockLogger.error).toHaveBeenCalled()
})

View File

@@ -1,6 +1,6 @@
import { type NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'

View File

@@ -51,7 +51,7 @@ describe('OAuth Connections API Route', () => {
jwtDecode: vi.fn(),
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
})
@@ -96,7 +96,7 @@ describe('OAuth Connections API Route', () => {
mockDb.limit.mockResolvedValueOnce(mockUserRecord)
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/connections/route')
const response = await GET(req)
const data = await response.json()
@@ -121,7 +121,7 @@ describe('OAuth Connections API Route', () => {
mockGetSession.mockResolvedValueOnce(null)
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/connections/route')
const response = await GET(req)
const data = await response.json()
@@ -146,7 +146,7 @@ describe('OAuth Connections API Route', () => {
mockDb.limit.mockResolvedValueOnce([])
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/connections/route')
const response = await GET(req)
const data = await response.json()
@@ -165,7 +165,7 @@ describe('OAuth Connections API Route', () => {
mockDb.where.mockRejectedValueOnce(new Error('Database error'))
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/connections/route')
const response = await GET(req)
const data = await response.json()
@@ -209,7 +209,7 @@ describe('OAuth Connections API Route', () => {
mockDb.limit.mockResolvedValueOnce([])
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/connections/route')
const response = await GET(req)
const data = await response.json()

View File

@@ -2,7 +2,7 @@ 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 { createLogger } from '@/lib/logs/console/logger'
import { db } from '@/db'
import { account, user } from '@/db/schema'

View File

@@ -63,7 +63,7 @@ describe('OAuth Credentials API Route', () => {
jwtDecode: vi.fn(),
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
})
@@ -111,7 +111,7 @@ describe('OAuth Credentials API Route', () => {
const req = createMockRequestWithQuery('GET', '?provider=google-email')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/credentials/route')
const response = await GET(req)
const data = await response.json()
@@ -135,7 +135,7 @@ describe('OAuth Credentials API Route', () => {
const req = createMockRequestWithQuery('GET', '?provider=google')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/credentials/route')
const response = await GET(req)
const data = await response.json()
@@ -152,7 +152,7 @@ describe('OAuth Credentials API Route', () => {
const req = createMockRequestWithQuery('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/credentials/route')
const response = await GET(req)
const data = await response.json()
@@ -177,7 +177,7 @@ describe('OAuth Credentials API Route', () => {
const req = createMockRequestWithQuery('GET', '?provider=github')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/credentials/route')
const response = await GET(req)
const data = await response.json()
@@ -220,7 +220,7 @@ describe('OAuth Credentials API Route', () => {
const req = createMockRequestWithQuery('GET', '?provider=google')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/credentials/route')
const response = await GET(req)
const data = await response.json()
@@ -244,7 +244,7 @@ describe('OAuth Credentials API Route', () => {
const req = createMockRequestWithQuery('GET', '?provider=google')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/credentials/route')
const response = await GET(req)
const data = await response.json()

View File

@@ -2,7 +2,7 @@ import { and, 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 { createLogger } from '@/lib/logs/console/logger'
import type { OAuthService } from '@/lib/oauth/oauth'
import { parseProvider } from '@/lib/oauth/oauth'
import { db } from '@/db'

View File

@@ -47,7 +47,7 @@ describe('OAuth Disconnect API Route', () => {
or: vi.fn((...conditions) => ({ conditions, type: 'or' })),
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
})
@@ -68,7 +68,7 @@ describe('OAuth Disconnect API Route', () => {
provider: 'google',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/disconnect/route')
const response = await POST(req)
const data = await response.json()
@@ -91,7 +91,7 @@ describe('OAuth Disconnect API Route', () => {
providerId: 'google-email',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/disconnect/route')
const response = await POST(req)
const data = await response.json()
@@ -108,7 +108,7 @@ describe('OAuth Disconnect API Route', () => {
provider: 'google',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/disconnect/route')
const response = await POST(req)
const data = await response.json()
@@ -125,7 +125,7 @@ describe('OAuth Disconnect API Route', () => {
const req = createMockRequest('POST', {})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/disconnect/route')
const response = await POST(req)
const data = await response.json()
@@ -147,7 +147,7 @@ describe('OAuth Disconnect API Route', () => {
provider: 'google',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/disconnect/route')
const response = await POST(req)
const data = await response.json()

View File

@@ -1,7 +1,7 @@
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 { createLogger } from '@/lib/logs/console/logger'
import { db } from '@/db'
import { account } from '@/db/schema'

View File

@@ -1,10 +1,10 @@
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 { createLogger } from '@/lib/logs/console/logger'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
import { db } from '@/db'
import { account } from '@/db/schema'
import { refreshAccessTokenIfNeeded } from '../../utils'
export const dynamic = 'force-dynamic'

View File

@@ -1,10 +1,10 @@
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 { createLogger } from '@/lib/logs/console/logger'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
import { db } from '@/db'
import { account } from '@/db/schema'
import { refreshAccessTokenIfNeeded } from '../../utils'
export const dynamic = 'force-dynamic'

View File

@@ -28,13 +28,13 @@ describe('OAuth Token API Routes', () => {
randomUUID: vi.fn().mockReturnValue(mockUUID),
})
vi.doMock('../utils', () => ({
vi.doMock('@/app/api/auth/oauth/utils', () => ({
getUserId: mockGetUserId,
getCredential: mockGetCredential,
refreshTokenIfNeeded: mockRefreshTokenIfNeeded,
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
})
@@ -67,7 +67,7 @@ describe('OAuth Token API Routes', () => {
})
// Import handler after setting up mocks
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/token/route')
// Call handler
const response = await POST(req)
@@ -102,7 +102,7 @@ describe('OAuth Token API Routes', () => {
workflowId: 'workflow-id',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/token/route')
const response = await POST(req)
const data = await response.json()
@@ -121,7 +121,7 @@ describe('OAuth Token API Routes', () => {
it('should handle missing credentialId', async () => {
const req = createMockRequest('POST', {})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/token/route')
const response = await POST(req)
const data = await response.json()
@@ -138,7 +138,7 @@ describe('OAuth Token API Routes', () => {
credentialId: 'credential-id',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/token/route')
const response = await POST(req)
const data = await response.json()
@@ -155,7 +155,7 @@ describe('OAuth Token API Routes', () => {
workflowId: 'nonexistent-workflow-id',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/token/route')
const response = await POST(req)
const data = await response.json()
@@ -172,7 +172,7 @@ describe('OAuth Token API Routes', () => {
credentialId: 'nonexistent-credential-id',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/token/route')
const response = await POST(req)
const data = await response.json()
@@ -196,7 +196,7 @@ describe('OAuth Token API Routes', () => {
credentialId: 'credential-id',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/oauth/token/route')
const response = await POST(req)
const data = await response.json()
@@ -228,7 +228,7 @@ describe('OAuth Token API Routes', () => {
'http://localhost:3000/api/auth/oauth/token?credentialId=credential-id'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/token/route')
const response = await GET(req as any)
const data = await response.json()
@@ -244,7 +244,7 @@ describe('OAuth Token API Routes', () => {
it('should handle missing credentialId', async () => {
const req = new Request('http://localhost:3000/api/auth/oauth/token')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/token/route')
const response = await GET(req as any)
const data = await response.json()
@@ -261,7 +261,7 @@ describe('OAuth Token API Routes', () => {
'http://localhost:3000/api/auth/oauth/token?credentialId=credential-id'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/token/route')
const response = await GET(req as any)
const data = await response.json()
@@ -278,7 +278,7 @@ describe('OAuth Token API Routes', () => {
'http://localhost:3000/api/auth/oauth/token?credentialId=nonexistent-credential-id'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/token/route')
const response = await GET(req as any)
const data = await response.json()
@@ -300,7 +300,7 @@ describe('OAuth Token API Routes', () => {
'http://localhost:3000/api/auth/oauth/token?credentialId=credential-id'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/token/route')
const response = await GET(req as any)
const data = await response.json()
@@ -325,7 +325,7 @@ describe('OAuth Token API Routes', () => {
'http://localhost:3000/api/auth/oauth/token?credentialId=credential-id'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/auth/oauth/token/route')
const response = await GET(req as any)
const data = await response.json()

View File

@@ -1,6 +1,6 @@
import { type NextRequest, NextResponse } from 'next/server'
import { createLogger } from '@/lib/logs/console-logger'
import { getCredential, getUserId, refreshTokenIfNeeded } from '../utils'
import { createLogger } from '@/lib/logs/console/logger'
import { getCredential, getUserId, refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'
export const dynamic = 'force-dynamic'

View File

@@ -39,7 +39,7 @@ describe('OAuth Utils', () => {
refreshOAuthToken: mockRefreshOAuthToken,
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
})
@@ -50,7 +50,7 @@ describe('OAuth Utils', () => {
describe('getUserId', () => {
it('should get user ID from session when no workflowId is provided', async () => {
const { getUserId } = await import('./utils')
const { getUserId } = await import('@/app/api/auth/oauth/utils')
const userId = await getUserId('request-id')
@@ -60,7 +60,7 @@ describe('OAuth Utils', () => {
it('should get user ID from workflow when workflowId is provided', async () => {
mockDb.limit.mockReturnValueOnce([{ userId: 'workflow-owner-id' }])
const { getUserId } = await import('./utils')
const { getUserId } = await import('@/app/api/auth/oauth/utils')
const userId = await getUserId('request-id', 'workflow-id')
@@ -76,7 +76,7 @@ describe('OAuth Utils', () => {
getSession: vi.fn().mockResolvedValue(null),
}))
const { getUserId } = await import('./utils')
const { getUserId } = await import('@/app/api/auth/oauth/utils')
const userId = await getUserId('request-id')
@@ -87,7 +87,7 @@ describe('OAuth Utils', () => {
it('should return undefined if workflow is not found', async () => {
mockDb.limit.mockReturnValueOnce([])
const { getUserId } = await import('./utils')
const { getUserId } = await import('@/app/api/auth/oauth/utils')
const userId = await getUserId('request-id', 'nonexistent-workflow-id')
@@ -101,7 +101,7 @@ describe('OAuth Utils', () => {
const mockCredential = { id: 'credential-id', userId: 'test-user-id' }
mockDb.limit.mockReturnValueOnce([mockCredential])
const { getCredential } = await import('./utils')
const { getCredential } = await import('@/app/api/auth/oauth/utils')
const credential = await getCredential('request-id', 'credential-id', 'test-user-id')
@@ -116,7 +116,7 @@ describe('OAuth Utils', () => {
it('should return undefined when credential is not found', async () => {
mockDb.limit.mockReturnValueOnce([])
const { getCredential } = await import('./utils')
const { getCredential } = await import('@/app/api/auth/oauth/utils')
const credential = await getCredential('request-id', 'nonexistent-id', 'test-user-id')
@@ -135,7 +135,7 @@ describe('OAuth Utils', () => {
providerId: 'google',
}
const { refreshTokenIfNeeded } = await import('./utils')
const { refreshTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
const result = await refreshTokenIfNeeded('request-id', mockCredential, 'credential-id')
@@ -159,7 +159,7 @@ describe('OAuth Utils', () => {
refreshToken: 'new-refresh-token',
})
const { refreshTokenIfNeeded } = await import('./utils')
const { refreshTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
const result = await refreshTokenIfNeeded('request-id', mockCredential, 'credential-id')
@@ -183,7 +183,7 @@ describe('OAuth Utils', () => {
mockRefreshOAuthToken.mockResolvedValueOnce(null)
const { refreshTokenIfNeeded } = await import('./utils')
const { refreshTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
await expect(
refreshTokenIfNeeded('request-id', mockCredential, 'credential-id')
@@ -201,7 +201,7 @@ describe('OAuth Utils', () => {
providerId: 'google',
}
const { refreshTokenIfNeeded } = await import('./utils')
const { refreshTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
const result = await refreshTokenIfNeeded('request-id', mockCredential, 'credential-id')
@@ -222,7 +222,7 @@ describe('OAuth Utils', () => {
}
mockDb.limit.mockReturnValueOnce([mockCredential])
const { refreshAccessTokenIfNeeded } = await import('./utils')
const { refreshAccessTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
const token = await refreshAccessTokenIfNeeded('credential-id', 'test-user-id', 'request-id')
@@ -247,7 +247,7 @@ describe('OAuth Utils', () => {
refreshToken: 'new-refresh-token',
})
const { refreshAccessTokenIfNeeded } = await import('./utils')
const { refreshAccessTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
const token = await refreshAccessTokenIfNeeded('credential-id', 'test-user-id', 'request-id')
@@ -260,7 +260,7 @@ describe('OAuth Utils', () => {
it('should return null if credential not found', async () => {
mockDb.limit.mockReturnValueOnce([])
const { refreshAccessTokenIfNeeded } = await import('./utils')
const { refreshAccessTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
const token = await refreshAccessTokenIfNeeded('nonexistent-id', 'test-user-id', 'request-id')
@@ -281,7 +281,7 @@ describe('OAuth Utils', () => {
mockRefreshOAuthToken.mockResolvedValueOnce(null)
const { refreshAccessTokenIfNeeded } = await import('./utils')
const { refreshAccessTokenIfNeeded } = await import('@/app/api/auth/oauth/utils')
const token = await refreshAccessTokenIfNeeded('credential-id', 'test-user-id', 'request-id')

View File

@@ -1,6 +1,6 @@
import { and, eq } from 'drizzle-orm'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { refreshOAuthToken } from '@/lib/oauth/oauth'
import { db } from '@/db'
import { account, workflow } from '@/db/schema'

View File

@@ -1,10 +1,10 @@
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 { createLogger } from '@/lib/logs/console/logger'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
import { db } from '@/db'
import { account } from '@/db/schema'
import { refreshAccessTokenIfNeeded } from '../../utils'
export const dynamic = 'force-dynamic'

View File

@@ -1,10 +1,10 @@
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 { createLogger } from '@/lib/logs/console/logger'
import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils'
import { db } from '@/db'
import { account } from '@/db/schema'
import { refreshAccessTokenIfNeeded } from '../../utils'
export const dynamic = 'force-dynamic'

View File

@@ -27,7 +27,7 @@ describe('Reset Password API Route', () => {
newPassword: 'newSecurePassword123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/reset-password/route')
const response = await POST(req)
const data = await response.json()
@@ -52,7 +52,7 @@ describe('Reset Password API Route', () => {
newPassword: 'newSecurePassword123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/reset-password/route')
const response = await POST(req)
const data = await response.json()
@@ -91,7 +91,7 @@ describe('Reset Password API Route', () => {
newPassword: 'newSecurePassword123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/reset-password/route')
const response = await POST(req)
const data = await response.json()
@@ -111,7 +111,7 @@ describe('Reset Password API Route', () => {
newPassword: '',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/reset-password/route')
const response = await POST(req)
const data = await response.json()
@@ -140,7 +140,7 @@ describe('Reset Password API Route', () => {
newPassword: 'newSecurePassword123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/reset-password/route')
const response = await POST(req)
const data = await response.json()
@@ -148,8 +148,8 @@ describe('Reset Password API Route', () => {
expect(response.status).toBe(500)
expect(data.message).toBe(errorMessage)
const logger = await import('@/lib/logs/console-logger')
const mockLogger = logger.createLogger('PasswordReset')
const logger = await import('@/lib/logs/console/logger')
const mockLogger = logger.createLogger('PasswordResetAPI')
expect(mockLogger.error).toHaveBeenCalledWith('Error during password reset:', {
error: expect.any(Error),
})
@@ -171,7 +171,7 @@ describe('Reset Password API Route', () => {
newPassword: 'newSecurePassword123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/auth/reset-password/route')
const response = await POST(req)
const data = await response.json()
@@ -181,8 +181,8 @@ describe('Reset Password API Route', () => {
'Failed to reset password. Please try again or request a new reset link.'
)
const logger = await import('@/lib/logs/console-logger')
const mockLogger = logger.createLogger('PasswordReset')
const logger = await import('@/lib/logs/console/logger')
const mockLogger = logger.createLogger('PasswordResetAPI')
expect(mockLogger.error).toHaveBeenCalled()
})
})

View File

@@ -1,10 +1,10 @@
import { type NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
const logger = createLogger('PasswordReset')
const logger = createLogger('PasswordResetAPI')
export async function POST(request: NextRequest) {
try {

View File

@@ -1,7 +1,7 @@
import { type NextRequest, NextResponse } from 'next/server'
import { verifyCronAuth } from '@/lib/auth/internal'
import { processDailyBillingCheck } from '@/lib/billing/core/billing'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('DailyBillingCron')

View File

@@ -3,12 +3,14 @@ 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-billing'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { db } from '@/db'
import { member } from '@/db/schema'
const logger = createLogger('UnifiedBillingAPI')
export const dynamic = 'force-dynamic'
/**
* Unified Billing Endpoint
*/

View File

@@ -4,7 +4,7 @@ import type Stripe from 'stripe'
import { requireStripeClient } from '@/lib/billing/stripe-client'
import { handleInvoiceWebhook } from '@/lib/billing/webhooks/stripe-invoice-webhooks'
import { env } from '@/lib/env'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('StripeInvoiceWebhook')

View File

@@ -3,12 +3,12 @@ import type { NextRequest } from 'next/server'
import { z } from 'zod'
import { renderOTPEmail } from '@/components/emails/render-email'
import { sendEmail } from '@/lib/email/mailer'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { getRedisClient, markMessageAsProcessed, releaseLock } from '@/lib/redis'
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'
import { addCorsHeaders, setChatAuthCookie } from '../../utils'
const logger = createLogger('ChatOtpAPI')

View File

@@ -67,7 +67,7 @@ describe('Chat Subdomain API Route', () => {
beforeEach(() => {
vi.resetModules()
vi.doMock('../utils', () => ({
vi.doMock('@/app/api/chat/utils', () => ({
addCorsHeaders: mockAddCorsHeaders,
validateChatAuth: mockValidateChatAuth,
setChatAuthCookie: mockSetChatAuthCookie,
@@ -75,7 +75,7 @@ describe('Chat Subdomain API Route', () => {
executeWorkflowForChat: mockExecuteWorkflowForChat,
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue({
debug: vi.fn(),
info: vi.fn(),
@@ -138,7 +138,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('GET')
const params = Promise.resolve({ subdomain: 'test-chat' })
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/[subdomain]/route')
const response = await GET(req, { params })
@@ -169,7 +169,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('GET')
const params = Promise.resolve({ subdomain: 'nonexistent' })
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/[subdomain]/route')
const response = await GET(req, { params })
@@ -203,7 +203,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('GET')
const params = Promise.resolve({ subdomain: 'inactive-chat' })
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/[subdomain]/route')
const response = await GET(req, { params })
@@ -224,7 +224,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('GET')
const params = Promise.resolve({ subdomain: 'password-protected-chat' })
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/[subdomain]/route')
const response = await GET(req, { params })
@@ -245,7 +245,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', { password: 'test-password' })
const params = Promise.resolve({ subdomain: 'password-protected-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -261,7 +261,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', {})
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -282,7 +282,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', { input: 'Hello' })
const params = Promise.resolve({ subdomain: 'protected-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -345,7 +345,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', { input: 'Hello' })
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -360,7 +360,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', { input: 'Hello world', conversationId: 'conv-123' })
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -377,7 +377,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', { input: 'Hello world' })
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -407,7 +407,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', { input: 'Trigger error' })
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -426,12 +426,13 @@ describe('Chat Subdomain API Route', () => {
// Create a request with invalid JSON
const req = {
method: 'POST',
headers: new Headers(),
json: vi.fn().mockRejectedValue(new Error('Invalid JSON')),
} as any
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
const response = await POST(req, { params })
@@ -449,7 +450,7 @@ describe('Chat Subdomain API Route', () => {
})
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
await POST(req, { params })
@@ -464,7 +465,7 @@ describe('Chat Subdomain API Route', () => {
const req = createMockRequest('POST', { input: 'Hello world' })
const params = Promise.resolve({ subdomain: 'test-chat' })
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/[subdomain]/route')
await POST(req, { params })

View File

@@ -1,16 +1,16 @@
import { eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { createLogger } from '@/lib/logs/console-logger'
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
import { db } from '@/db'
import { chat, workflow } from '@/db/schema'
import { createLogger } from '@/lib/logs/console/logger'
import {
addCorsHeaders,
executeWorkflowForChat,
setChatAuthCookie,
validateAuthToken,
validateChatAuth,
} from '../utils'
} 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')

View File

@@ -42,7 +42,7 @@ describe('Chat Edit API Route', () => {
chat: { id: 'id', subdomain: 'subdomain', userId: 'userId' },
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue({
info: vi.fn(),
error: vi.fn(),
@@ -94,7 +94,7 @@ describe('Chat Edit API Route', () => {
}))
const req = new NextRequest('http://localhost:3000/api/chat/edit/chat-123')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/edit/[id]/route')
const response = await GET(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(401)
@@ -111,7 +111,7 @@ describe('Chat Edit API Route', () => {
mockCheckChatAccess.mockResolvedValue({ hasAccess: false })
const req = new NextRequest('http://localhost:3000/api/chat/edit/chat-123')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/edit/[id]/route')
const response = await GET(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(404)
@@ -138,7 +138,7 @@ describe('Chat Edit API Route', () => {
mockCheckChatAccess.mockResolvedValue({ hasAccess: true, chat: mockChat })
const req = new NextRequest('http://localhost:3000/api/chat/edit/chat-123')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/edit/[id]/route')
const response = await GET(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(200)
@@ -164,7 +164,7 @@ describe('Chat Edit API Route', () => {
method: 'PATCH',
body: JSON.stringify({ title: 'Updated Chat' }),
})
const { PATCH } = await import('./route')
const { PATCH } = await import('@/app/api/chat/edit/[id]/route')
const response = await PATCH(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(401)
@@ -184,7 +184,7 @@ describe('Chat Edit API Route', () => {
method: 'PATCH',
body: JSON.stringify({ title: 'Updated Chat' }),
})
const { PATCH } = await import('./route')
const { PATCH } = await import('@/app/api/chat/edit/[id]/route')
const response = await PATCH(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(404)
@@ -212,7 +212,7 @@ describe('Chat Edit API Route', () => {
method: 'PATCH',
body: JSON.stringify({ title: 'Updated Chat', description: 'Updated description' }),
})
const { PATCH } = await import('./route')
const { PATCH } = await import('@/app/api/chat/edit/[id]/route')
const response = await PATCH(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(200)
@@ -245,7 +245,7 @@ describe('Chat Edit API Route', () => {
method: 'PATCH',
body: JSON.stringify({ subdomain: 'new-subdomain' }),
})
const { PATCH } = await import('./route')
const { PATCH } = await import('@/app/api/chat/edit/[id]/route')
const response = await PATCH(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(400)
@@ -273,7 +273,7 @@ describe('Chat Edit API Route', () => {
method: 'PATCH',
body: JSON.stringify({ authType: 'password' }), // No password provided
})
const { PATCH } = await import('./route')
const { PATCH } = await import('@/app/api/chat/edit/[id]/route')
const response = await PATCH(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(400)
@@ -304,7 +304,7 @@ describe('Chat Edit API Route', () => {
method: 'PATCH',
body: JSON.stringify({ title: 'Admin Updated Chat' }),
})
const { PATCH } = await import('./route')
const { PATCH } = await import('@/app/api/chat/edit/[id]/route')
const response = await PATCH(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(200)
@@ -321,7 +321,7 @@ describe('Chat Edit API Route', () => {
const req = new NextRequest('http://localhost:3000/api/chat/edit/chat-123', {
method: 'DELETE',
})
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/chat/edit/[id]/route')
const response = await DELETE(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(401)
@@ -340,7 +340,7 @@ describe('Chat Edit API Route', () => {
const req = new NextRequest('http://localhost:3000/api/chat/edit/chat-123', {
method: 'DELETE',
})
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/chat/edit/[id]/route')
const response = await DELETE(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(404)
@@ -361,7 +361,7 @@ describe('Chat Edit API Route', () => {
const req = new NextRequest('http://localhost:3000/api/chat/edit/chat-123', {
method: 'DELETE',
})
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/chat/edit/[id]/route')
const response = await DELETE(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(200)
@@ -385,7 +385,7 @@ describe('Chat Edit API Route', () => {
const req = new NextRequest('http://localhost:3000/api/chat/edit/chat-123', {
method: 'DELETE',
})
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/chat/edit/[id]/route')
const response = await DELETE(req, { params: Promise.resolve({ id: 'chat-123' }) })
expect(response.status).toBe(200)

View File

@@ -3,7 +3,7 @@ import type { NextRequest } from 'next/server'
import { z } from 'zod'
import { getSession } from '@/lib/auth'
import { isDev } from '@/lib/environment'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { getEmailDomain } from '@/lib/urls/utils'
import { encryptSecret } from '@/lib/utils'
import { checkChatAccess } from '@/app/api/chat/utils'

View File

@@ -41,7 +41,7 @@ describe('Chat API Route', () => {
workflow: { id: 'id', userId: 'userId', isDeployed: 'isDeployed' },
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue({
info: vi.fn(),
error: vi.fn(),
@@ -89,7 +89,7 @@ describe('Chat API Route', () => {
}))
const req = new NextRequest('http://localhost:3000/api/chat')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/route')
const response = await GET(req)
expect(response.status).toBe(401)
@@ -107,7 +107,7 @@ describe('Chat API Route', () => {
mockWhere.mockResolvedValue(mockDeployments)
const req = new NextRequest('http://localhost:3000/api/chat')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/route')
const response = await GET(req)
expect(response.status).toBe(200)
@@ -125,7 +125,7 @@ describe('Chat API Route', () => {
mockWhere.mockRejectedValue(new Error('Database error'))
const req = new NextRequest('http://localhost:3000/api/chat')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/route')
const response = await GET(req)
expect(response.status).toBe(500)
@@ -143,7 +143,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify({}),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(401)
@@ -163,7 +163,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(invalidData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(400)
@@ -192,7 +192,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(validData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(400)
@@ -223,7 +223,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(validData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(404)
@@ -268,7 +268,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(validData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -310,7 +310,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(validData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -343,7 +343,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(validData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(404)
@@ -378,7 +378,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(validData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(500)
@@ -412,7 +412,7 @@ describe('Chat API Route', () => {
method: 'POST',
body: JSON.stringify(validData),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/chat/route')
const response = await POST(req)
expect(response.status).toBe(400)

View File

@@ -5,7 +5,7 @@ import { z } from 'zod'
import { getSession } from '@/lib/auth'
import { env } from '@/lib/env'
import { isDev } from '@/lib/environment'
import { createLogger } from '@/lib/logs/console-logger'
import { 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'
@@ -14,6 +14,8 @@ import { chat } from '@/db/schema'
const logger = createLogger('ChatAPI')
export const dynamic = 'force-dynamic'
const chatSchema = z.object({
workflowId: z.string().min(1, 'Workflow ID is required'),
subdomain: z

View File

@@ -41,7 +41,7 @@ describe('Subdomain Validation API Route', () => {
}))
// Mock the logger
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue({
info: vi.fn(),
error: vi.fn(),
@@ -93,7 +93,7 @@ describe('Subdomain Validation API Route', () => {
const req = new NextRequest('http://localhost:3000/api/chat/subdomains/validate?subdomain=test')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/subdomains/validate/route')
const response = await GET(req)
@@ -110,7 +110,7 @@ describe('Subdomain Validation API Route', () => {
const req = new NextRequest('http://localhost:3000/api/chat/subdomains/validate')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/subdomains/validate/route')
const response = await GET(req)
@@ -129,7 +129,7 @@ describe('Subdomain Validation API Route', () => {
'http://localhost:3000/api/chat/subdomains/validate?subdomain=Invalid_Subdomain!'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/subdomains/validate/route')
const response = await GET(req)
const data = await response.json()
@@ -156,7 +156,7 @@ describe('Subdomain Validation API Route', () => {
'http://localhost:3000/api/chat/subdomains/validate?subdomain=available-subdomain'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/subdomains/validate/route')
const response = await GET(req)
@@ -178,7 +178,7 @@ describe('Subdomain Validation API Route', () => {
'http://localhost:3000/api/chat/subdomains/validate?subdomain=telemetry'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/subdomains/validate/route')
const response = await GET(req)
const data = await response.json()
@@ -205,7 +205,7 @@ describe('Subdomain Validation API Route', () => {
'http://localhost:3000/api/chat/subdomains/validate?subdomain=used-subdomain'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/subdomains/validate/route')
const response = await GET(req)
@@ -229,7 +229,7 @@ describe('Subdomain Validation API Route', () => {
'http://localhost:3000/api/chat/subdomains/validate?subdomain=error-subdomain'
)
const { GET } = await import('./route')
const { GET } = await import('@/app/api/chat/subdomains/validate/route')
const response = await GET(req)

View File

@@ -1,7 +1,10 @@
import { eq } from 'drizzle-orm'
import { NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
import { db } from '@/db'
import { chat } from '@/db/schema'

View File

@@ -18,8 +18,8 @@ vi.mock('@/lib/utils', () => ({
decryptSecret: vi.fn().mockResolvedValue({ decrypted: 'test-secret' }),
}))
vi.mock('@/lib/logs/enhanced-logging-session', () => ({
EnhancedLoggingSession: vi.fn().mockImplementation(() => ({
vi.mock('@/lib/logs/execution/logging-session', () => ({
LoggingSession: vi.fn().mockImplementation(() => ({
safeStart: vi.fn().mockResolvedValue(undefined),
safeComplete: vi.fn().mockResolvedValue(undefined),
safeCompleteWithError: vi.fn().mockResolvedValue(undefined),
@@ -42,7 +42,7 @@ describe('Chat API Utils', () => {
beforeEach(() => {
vi.resetModules()
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue({
info: vi.fn(),
error: vi.fn(),
@@ -66,7 +66,7 @@ describe('Chat API Utils', () => {
describe('Auth token utils', () => {
it.concurrent('should encrypt and validate auth tokens', async () => {
const { encryptAuthToken, validateAuthToken } = await import('./utils')
const { encryptAuthToken, validateAuthToken } = await import('@/app/api/chat/utils')
const subdomainId = 'test-subdomain-id'
const type = 'password'
@@ -83,7 +83,7 @@ describe('Chat API Utils', () => {
})
it.concurrent('should reject expired tokens', async () => {
const { validateAuthToken } = await import('./utils')
const { validateAuthToken } = await import('@/app/api/chat/utils')
const subdomainId = 'test-subdomain-id'
// Create an expired token by directly constructing it with an old timestamp
@@ -98,7 +98,7 @@ describe('Chat API Utils', () => {
describe('Cookie handling', () => {
it.concurrent('should set auth cookie correctly', async () => {
const { setChatAuthCookie } = await import('./utils')
const { setChatAuthCookie } = await import('@/app/api/chat/utils')
const mockSet = vi.fn()
const mockResponse = {
@@ -127,7 +127,7 @@ describe('Chat API Utils', () => {
describe('CORS handling', () => {
it.concurrent('should add CORS headers for localhost in development', async () => {
const { addCorsHeaders } = await import('./utils')
const { addCorsHeaders } = await import('@/app/api/chat/utils')
const mockRequest = {
headers: {
@@ -162,7 +162,7 @@ describe('Chat API Utils', () => {
})
it.concurrent('should handle OPTIONS request', async () => {
const { OPTIONS } = await import('./utils')
const { OPTIONS } = await import('@/app/api/chat/utils')
const mockRequest = {
headers: {
@@ -178,7 +178,7 @@ describe('Chat API Utils', () => {
describe('Chat auth validation', () => {
beforeEach(() => {
vi.doMock('./utils', async (importOriginal) => {
vi.doMock('@/app/api/chat/utils', async (importOriginal) => {
const original = (await importOriginal()) as any
return {
...original,
@@ -200,7 +200,7 @@ describe('Chat API Utils', () => {
})
it.concurrent('should allow access to public chats', async () => {
const utils = await import('./utils')
const utils = await import('@/app/api/chat/utils')
const { validateChatAuth } = utils
const deployment = {
@@ -220,7 +220,7 @@ describe('Chat API Utils', () => {
})
it.concurrent('should request password auth for GET requests', async () => {
const { validateChatAuth } = await import('./utils')
const { validateChatAuth } = await import('@/app/api/chat/utils')
const deployment = {
id: 'chat-id',
@@ -241,7 +241,7 @@ describe('Chat API Utils', () => {
})
it('should validate password for POST requests', async () => {
const { validateChatAuth } = await import('./utils')
const { validateChatAuth } = await import('@/app/api/chat/utils')
const { decryptSecret } = await import('@/lib/utils')
const deployment = {
@@ -268,7 +268,7 @@ describe('Chat API Utils', () => {
})
it.concurrent('should reject incorrect password', async () => {
const { validateChatAuth } = await import('./utils')
const { validateChatAuth } = await import('@/app/api/chat/utils')
const deployment = {
id: 'chat-id',
@@ -294,7 +294,7 @@ describe('Chat API Utils', () => {
})
it.concurrent('should request email auth for email-protected chats', async () => {
const { validateChatAuth } = await import('./utils')
const { validateChatAuth } = await import('@/app/api/chat/utils')
const deployment = {
id: 'chat-id',
@@ -316,7 +316,7 @@ describe('Chat API Utils', () => {
})
it.concurrent('should check allowed emails for email auth', async () => {
const { validateChatAuth } = await import('./utils')
const { validateChatAuth } = await import('@/app/api/chat/utils')
const deployment = {
id: 'chat-id',

View File

@@ -2,9 +2,9 @@ import { eq, sql } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { v4 as uuidv4 } from 'uuid'
import { isDev } from '@/lib/environment'
import { createLogger } from '@/lib/logs/console-logger'
import { EnhancedLoggingSession } from '@/lib/logs/enhanced-logging-session'
import { buildTraceSpans } from '@/lib/logs/trace-spans'
import { createLogger } from '@/lib/logs/console/logger'
import { LoggingSession } from '@/lib/logs/execution/logging-session'
import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans'
import { hasAdminPermission } from '@/lib/permissions/utils'
import { processStreamingBlockLogs } from '@/lib/tokenization'
import { getEmailDomain } from '@/lib/urls/utils'
@@ -330,8 +330,8 @@ export async function executeWorkflowForChat(
const workflowId = deployment.workflowId
const executionId = uuidv4()
// Set up enhanced logging for chat execution
const loggingSession = new EnhancedLoggingSession(workflowId, executionId, 'chat', requestId)
// Set up logging for chat execution
const loggingSession = new LoggingSession(workflowId, executionId, 'chat', requestId)
// Check for multi-output configuration in customizations
const customizations = (deployment.customizations || {}) as Record<string, any>
@@ -494,7 +494,7 @@ export async function executeWorkflowForChat(
{} as Record<string, Record<string, any>>
)
// Start enhanced logging session
// Start logging session
await loggingSession.safeStart({
userId: deployment.userId,
workspaceId: '', // TODO: Get from workflow
@@ -552,7 +552,7 @@ export async function executeWorkflowForChat(
},
})
// Set up enhanced logging on the executor
// Set up logging on the executor
loggingSession.setupExecutor(executor)
let result
@@ -624,7 +624,7 @@ export async function executeWorkflowForChat(
)
}
// Complete enhanced logging session (for both success and failure)
// Complete logging session (for both success and failure)
if (result && 'success' in result) {
const { traceSpans } = buildTraceSpans(result)
await loggingSession.safeComplete({

View File

@@ -51,7 +51,7 @@ describe('Codegen API Route', () => {
env: mockEnv,
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
@@ -94,7 +94,7 @@ describe('Codegen API Route', () => {
generationType: 'json-schema',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()
@@ -136,7 +136,7 @@ describe('Codegen API Route', () => {
generationType: 'javascript-function-body',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()
@@ -188,7 +188,7 @@ describe('Codegen API Route', () => {
generationType: 'custom-tool-schema',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()
@@ -217,7 +217,7 @@ describe('Codegen API Route', () => {
context: 'existing function code here',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
@@ -260,7 +260,7 @@ describe('Codegen API Route', () => {
],
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
@@ -287,7 +287,7 @@ describe('Codegen API Route', () => {
generationType: 'json-schema',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()
@@ -302,7 +302,7 @@ describe('Codegen API Route', () => {
prompt: '',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()
@@ -319,7 +319,7 @@ describe('Codegen API Route', () => {
generationType: 'invalid-type',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()
@@ -348,7 +348,7 @@ describe('Codegen API Route', () => {
generationType: 'javascript-function-body',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()
@@ -377,7 +377,7 @@ describe('Codegen API Route', () => {
generationType: 'json-schema',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/codegen/route')
const response = await POST(req)
const data = await response.json()

View File

@@ -2,7 +2,7 @@ import { unstable_noStore as noStore } from 'next/cache'
import { type NextRequest, NextResponse } from 'next/server'
import OpenAI from 'openai'
import { env } from '@/lib/env'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
export const runtime = 'edge'

View File

@@ -1,7 +1,7 @@
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 { createLogger } from '@/lib/logs/console/logger'
import { db } from '@/db'
import { copilotCheckpoints, workflow as workflowTable } from '@/db/schema'

View File

@@ -1,7 +1,7 @@
import { and, desc, eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { db } from '@/db'
import { copilotCheckpoints } from '@/db/schema'

View File

@@ -10,7 +10,7 @@ import {
sendMessage,
updateChat,
} from '@/lib/copilot/service'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('CopilotAPI')

View File

@@ -1,6 +1,6 @@
import { type NextRequest, NextResponse } from 'next/server'
import { searchDocumentation } from '@/lib/copilot/service'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
const logger = createLogger('DocsSearchAPI')

View File

@@ -2,7 +2,10 @@ 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 { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
import { decryptSecret, encryptSecret } from '@/lib/utils'
import { db } from '@/db'
import { environment } from '@/db/schema'

View File

@@ -21,7 +21,7 @@ describe('File Delete API Route', () => {
filePath: '/api/files/serve/test-file.txt',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/delete/route')
const response = await POST(req)
const data = await response.json()
@@ -42,7 +42,7 @@ describe('File Delete API Route', () => {
filePath: '/api/files/serve/nonexistent.txt',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/delete/route')
const response = await POST(req)
const data = await response.json()
@@ -74,7 +74,7 @@ describe('File Delete API Route', () => {
filePath: '/api/files/serve/s3/1234567890-test-file.txt',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/delete/route')
const response = await POST(req)
const data = await response.json()
@@ -109,7 +109,7 @@ describe('File Delete API Route', () => {
filePath: '/api/files/serve/blob/1234567890-test-document.pdf',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/delete/route')
const response = await POST(req)
const data = await response.json()
@@ -127,7 +127,7 @@ describe('File Delete API Route', () => {
const req = createMockRequest('POST', {})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/delete/route')
const response = await POST(req)
const data = await response.json()
@@ -138,7 +138,7 @@ describe('File Delete API Route', () => {
})
it('should handle CORS preflight requests', async () => {
const { OPTIONS } = await import('./route')
const { OPTIONS } = await import('@/app/api/files/delete/route')
const response = await OPTIONS()

View File

@@ -2,7 +2,7 @@ import { existsSync } from 'fs'
import { unlink } from 'fs/promises'
import { join } from 'path'
import type { NextRequest } from 'next/server'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { deleteFile, isUsingCloudStorage } from '@/lib/uploads'
import { UPLOAD_DIR } from '@/lib/uploads/setup'
import '@/lib/uploads/setup.server'

View File

@@ -7,7 +7,7 @@ import { NextRequest } from 'next/server'
*/
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createMockRequest, setupFileApiMocks } from '@/app/api/__test-utils__/utils'
import { POST } from './route'
import { POST } from '@/app/api/files/parse/route'
const mockJoin = vi.fn((...args: string[]): string => {
if (args[0] === '/test/uploads') {
@@ -53,7 +53,7 @@ describe('File Parse API Route', () => {
setupFileApiMocks()
const req = createMockRequest('POST', {})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/parse/route')
const response = await POST(req)
const data = await response.json()
@@ -72,7 +72,7 @@ describe('File Parse API Route', () => {
filePath: '/api/files/serve/test-file.txt',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/parse/route')
const response = await POST(req)
const data = await response.json()
@@ -97,7 +97,7 @@ describe('File Parse API Route', () => {
filePath: '/api/files/serve/s3/test-file.pdf',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/parse/route')
const response = await POST(req)
const data = await response.json()
@@ -120,7 +120,7 @@ describe('File Parse API Route', () => {
filePath: ['/api/files/serve/file1.txt', '/api/files/serve/file2.txt'],
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/parse/route')
const response = await POST(req)
const data = await response.json()
@@ -157,7 +157,7 @@ describe('File Parse API Route', () => {
}),
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/parse/route')
const response = await POST(req)
const data = await response.json()
@@ -184,7 +184,7 @@ describe('File Parse API Route', () => {
filePath: '/api/files/serve/nonexistent.txt',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/parse/route')
const response = await POST(req)
const data = await response.json()

View File

@@ -5,7 +5,7 @@ import path from 'path'
import binaryExtensionsList from 'binary-extensions'
import { type NextRequest, NextResponse } from 'next/server'
import { isSupportedFileType, parseFile } from '@/lib/file-parsers'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { downloadFile, isUsingCloudStorage } from '@/lib/uploads'
import { UPLOAD_DIR } from '@/lib/uploads/setup'
import '@/lib/uploads/setup.server'

View File

@@ -25,7 +25,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -51,7 +51,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -75,7 +75,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -99,7 +99,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -124,7 +124,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const largeFileSize = 150 * 1024 * 1024 // 150MB (exceeds 100MB limit)
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
@@ -150,7 +150,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -182,7 +182,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest(
'http://localhost:3000/api/files/presigned?type=knowledge-base',
@@ -210,7 +210,7 @@ describe('/api/files/presigned', () => {
storageProvider: 'blob',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -250,7 +250,7 @@ describe('/api/files/presigned', () => {
isUsingCloudStorage: vi.fn().mockReturnValue(true),
}))
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -293,7 +293,7 @@ describe('/api/files/presigned', () => {
getSignedUrl: vi.fn().mockRejectedValue(new Error('S3 service unavailable')),
}))
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -339,7 +339,7 @@ describe('/api/files/presigned', () => {
sanitizeFilenameForMetadata: vi.fn((filename) => filename),
}))
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -364,7 +364,7 @@ describe('/api/files/presigned', () => {
storageProvider: 's3',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/presigned/route')
const request = new NextRequest('http://localhost:3000/api/files/presigned', {
method: 'POST',
@@ -382,7 +382,7 @@ describe('/api/files/presigned', () => {
describe('OPTIONS', () => {
it('should handle CORS preflight requests', async () => {
const { OPTIONS } = await import('./route')
const { OPTIONS } = await import('@/app/api/files/presigned/route')
const response = await OPTIONS()

View File

@@ -2,7 +2,7 @@ import { PutObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
import { type NextRequest, NextResponse } from 'next/server'
import { v4 as uuidv4 } from 'uuid'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { getStorageProvider, isUsingCloudStorage } from '@/lib/uploads'
import { getBlobServiceClient } from '@/lib/uploads/blob/blob-client'
import { getS3Client, sanitizeFilenameForMetadata } from '@/lib/uploads/s3/s3-client'

View File

@@ -61,7 +61,7 @@ describe('File Serve API Route', () => {
it('should serve local file successfully', async () => {
const req = new NextRequest('http://localhost:3000/api/files/serve/test-file.txt')
const params = { path: ['test-file.txt'] }
const { GET } = await import('./route')
const { GET } = await import('@/app/api/files/serve/[...path]/route')
const response = await GET(req, { params: Promise.resolve(params) })
@@ -107,7 +107,7 @@ describe('File Serve API Route', () => {
const req = new NextRequest('http://localhost:3000/api/files/serve/nested/path/file.txt')
const params = { path: ['nested', 'path', 'file.txt'] }
const { GET } = await import('./route')
const { GET } = await import('@/app/api/files/serve/[...path]/route')
const response = await GET(req, { params: Promise.resolve(params) })
@@ -163,7 +163,7 @@ describe('File Serve API Route', () => {
const req = new NextRequest('http://localhost:3000/api/files/serve/s3/1234567890-image.png')
const params = { path: ['s3', '1234567890-image.png'] }
const { GET } = await import('./route')
const { GET } = await import('@/app/api/files/serve/[...path]/route')
const response = await GET(req, { params: Promise.resolve(params) })
@@ -208,7 +208,7 @@ describe('File Serve API Route', () => {
const req = new NextRequest('http://localhost:3000/api/files/serve/nonexistent.txt')
const params = { path: ['nonexistent.txt'] }
const { GET } = await import('./route')
const { GET } = await import('@/app/api/files/serve/[...path]/route')
const response = await GET(req, { params: Promise.resolve(params) })
@@ -249,7 +249,7 @@ describe('File Serve API Route', () => {
const req = new NextRequest(`http://localhost:3000/api/files/serve/file.${test.ext}`)
const params = { path: [`file.${test.ext}`] }
const { GET } = await import('./route')
const { GET } = await import('@/app/api/files/serve/[...path]/route')
const response = await GET(req, { params: Promise.resolve(params) })

View File

@@ -1,6 +1,6 @@
import { readFile } from 'fs/promises'
import type { NextRequest, NextResponse } from 'next/server'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { downloadFile, getStorageProvider, isUsingCloudStorage } from '@/lib/uploads'
import { BLOB_KB_CONFIG, S3_KB_CONFIG } from '@/lib/uploads/setup'
import '@/lib/uploads/setup.server'

View File

@@ -47,7 +47,7 @@ describe('File Upload API Route', () => {
body: formData,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/upload/route')
const response = await POST(req)
const data = await response.json()
@@ -77,7 +77,7 @@ describe('File Upload API Route', () => {
body: formData,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/upload/route')
const response = await POST(req)
const data = await response.json()
@@ -108,7 +108,7 @@ describe('File Upload API Route', () => {
body: formData,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/upload/route')
const response = await POST(req)
const data = await response.json()
@@ -128,7 +128,7 @@ describe('File Upload API Route', () => {
body: formData,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/upload/route')
const response = await POST(req)
const data = await response.json()
@@ -157,7 +157,7 @@ describe('File Upload API Route', () => {
body: formData,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/files/upload/route')
const response = await POST(req)
const data = await response.json()
@@ -168,7 +168,7 @@ describe('File Upload API Route', () => {
})
it('should handle CORS preflight requests', async () => {
const { OPTIONS } = await import('./route')
const { OPTIONS } = await import('@/app/api/files/upload/route')
const response = await OPTIONS()

View File

@@ -2,13 +2,15 @@ import { writeFile } from 'fs/promises'
import { join } from 'path'
import { type NextRequest, NextResponse } from 'next/server'
import { v4 as uuidv4 } from 'uuid'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { isUsingCloudStorage, uploadFile } from '@/lib/uploads'
import { UPLOAD_DIR } from '@/lib/uploads/setup'
// Import to ensure the uploads directory is created
import '@/lib/uploads/setup.server'
import { createErrorResponse, createOptionsResponse, InvalidRequestError } from '../utils'
import {
createErrorResponse,
createOptionsResponse,
InvalidRequestError,
} from '@/app/api/files/utils'
export const dynamic = 'force-dynamic'

View File

@@ -135,7 +135,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -160,7 +160,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -178,7 +178,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -200,7 +200,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -222,7 +222,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -244,7 +244,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -266,7 +266,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -300,7 +300,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
await PUT(req, { params })
@@ -321,7 +321,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -347,7 +347,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -372,7 +372,7 @@ describe('Individual Folder API Route', () => {
const params = Promise.resolve({ id: 'folder-1' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -404,7 +404,7 @@ describe('Individual Folder API Route', () => {
})
const params = Promise.resolve({ id: 'folder-3' })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/folders/[id]/route')
const response = await PUT(req, { params })
@@ -430,7 +430,7 @@ describe('Individual Folder API Route', () => {
const req = createMockRequest('DELETE')
const params = Promise.resolve({ id: 'folder-1' })
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/folders/[id]/route')
const response = await DELETE(req, { params })
@@ -450,7 +450,7 @@ describe('Individual Folder API Route', () => {
const req = createMockRequest('DELETE')
const params = Promise.resolve({ id: 'folder-1' })
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/folders/[id]/route')
const response = await DELETE(req, { params })
@@ -470,7 +470,7 @@ describe('Individual Folder API Route', () => {
const req = createMockRequest('DELETE')
const params = Promise.resolve({ id: 'folder-1' })
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/folders/[id]/route')
const response = await DELETE(req, { params })
@@ -490,7 +490,7 @@ describe('Individual Folder API Route', () => {
const req = createMockRequest('DELETE')
const params = Promise.resolve({ id: 'folder-1' })
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/folders/[id]/route')
const response = await DELETE(req, { params })
@@ -512,7 +512,7 @@ describe('Individual Folder API Route', () => {
const req = createMockRequest('DELETE')
const params = Promise.resolve({ id: 'folder-1' })
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/folders/[id]/route')
const response = await DELETE(req, { params })
@@ -533,7 +533,7 @@ describe('Individual Folder API Route', () => {
const req = createMockRequest('DELETE')
const params = Promise.resolve({ id: 'folder-1' })
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/folders/[id]/route')
const response = await DELETE(req, { params })

View File

@@ -1,7 +1,10 @@
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 { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
import { getUserEntityPermissions } from '@/lib/permissions/utils'
import { db } from '@/db'
import { workflow, workflowFolder } from '@/db/schema'

View File

@@ -101,7 +101,7 @@ describe('Folders API Route', () => {
value: 'http://localhost:3000/api/folders?workspaceId=workspace-123',
})
const { GET } = await import('./route')
const { GET } = await import('@/app/api/folders/route')
const response = await GET(mockRequest)
expect(response.status).toBe(200)
@@ -124,7 +124,7 @@ describe('Folders API Route', () => {
value: 'http://localhost:3000/api/folders?workspaceId=workspace-123',
})
const { GET } = await import('./route')
const { GET } = await import('@/app/api/folders/route')
const response = await GET(mockRequest)
expect(response.status).toBe(401)
@@ -141,7 +141,7 @@ describe('Folders API Route', () => {
value: 'http://localhost:3000/api/folders',
})
const { GET } = await import('./route')
const { GET } = await import('@/app/api/folders/route')
const response = await GET(mockRequest)
expect(response.status).toBe(400)
@@ -159,7 +159,7 @@ describe('Folders API Route', () => {
value: 'http://localhost:3000/api/folders?workspaceId=workspace-123',
})
const { GET } = await import('./route')
const { GET } = await import('@/app/api/folders/route')
const response = await GET(mockRequest)
expect(response.status).toBe(403)
@@ -177,7 +177,7 @@ describe('Folders API Route', () => {
value: 'http://localhost:3000/api/folders?workspaceId=workspace-123',
})
const { GET } = await import('./route')
const { GET } = await import('@/app/api/folders/route')
const response = await GET(mockRequest)
expect(response.status).toBe(200) // Should work for read permissions
@@ -198,7 +198,7 @@ describe('Folders API Route', () => {
value: 'http://localhost:3000/api/folders?workspaceId=workspace-123',
})
const { GET } = await import('./route')
const { GET } = await import('@/app/api/folders/route')
const response = await GET(mockRequest)
expect(response.status).toBe(500)
@@ -241,7 +241,7 @@ describe('Folders API Route', () => {
color: '#6B7280',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -283,7 +283,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -310,7 +310,7 @@ describe('Folders API Route', () => {
parentId: 'folder-1',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -329,7 +329,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(401)
@@ -347,7 +347,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(403)
@@ -385,7 +385,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -423,7 +423,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -445,7 +445,7 @@ describe('Folders API Route', () => {
const req = createMockRequest('POST', body)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(400)
@@ -468,7 +468,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
const response = await POST(req)
expect(response.status).toBe(500)
@@ -513,7 +513,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
await POST(req)
expect(capturedValues).not.toBeNull()
@@ -553,7 +553,7 @@ describe('Folders API Route', () => {
workspaceId: 'workspace-123',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/folders/route')
await POST(req)
expect(capturedValues).not.toBeNull()

View File

@@ -1,13 +1,15 @@
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 { 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')
export const dynamic = 'force-dynamic'
// GET - Fetch folders for a workspace
export async function GET(request: NextRequest) {
try {

View File

@@ -41,7 +41,7 @@ describe('Function Execute API Route', () => {
},
}))
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
@@ -65,7 +65,7 @@ describe('Function Execute API Route', () => {
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -80,7 +80,7 @@ describe('Function Execute API Route', () => {
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -94,7 +94,7 @@ describe('Function Execute API Route', () => {
code: 'return "test"',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -116,7 +116,7 @@ describe('Function Execute API Route', () => {
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -131,7 +131,7 @@ describe('Function Execute API Route', () => {
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -149,7 +149,7 @@ describe('Function Execute API Route', () => {
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -165,7 +165,7 @@ describe('Function Execute API Route', () => {
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -199,7 +199,7 @@ describe('Function Execute API Route', () => {
params: gmailData,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -221,7 +221,7 @@ describe('Function Execute API Route', () => {
params: complexEmailData,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -234,7 +234,7 @@ describe('Function Execute API Route', () => {
code: 'return "freestyle test"',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
await POST(req)
expect(mockFreestyleExecuteScript).toHaveBeenCalled()
@@ -250,7 +250,7 @@ describe('Function Execute API Route', () => {
code: 'return "fallback test"',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(mockFreestyleExecuteScript).toHaveBeenCalled()
@@ -271,7 +271,7 @@ describe('Function Execute API Route', () => {
code: 'return undefinedVariable',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(500)
@@ -293,7 +293,7 @@ describe('Function Execute API Route', () => {
code: 'return "vm test"',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
await POST(req)
expect(mockFreestyleExecuteScript).not.toHaveBeenCalled()
@@ -319,7 +319,7 @@ describe('Function Execute API Route', () => {
code: 'return invalidCode(',
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(500)
@@ -339,7 +339,7 @@ describe('Function Execute API Route', () => {
isCustomTool: true,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -355,7 +355,7 @@ describe('Function Execute API Route', () => {
headers: { 'Content-Type': 'application/json' },
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(500)
@@ -367,7 +367,7 @@ describe('Function Execute API Route', () => {
timeout: 10000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
await POST(req)
expect(mockLogger.info).toHaveBeenCalledWith(
@@ -384,7 +384,7 @@ describe('Function Execute API Route', () => {
params: {},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -417,7 +417,7 @@ SyntaxError: Invalid or unexpected token
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -460,7 +460,7 @@ SyntaxError: Invalid or unexpected token
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -501,7 +501,7 @@ SyntaxError: Invalid or unexpected token
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -531,7 +531,7 @@ SyntaxError: Invalid or unexpected token
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -567,7 +567,7 @@ SyntaxError: Invalid or unexpected token
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -598,7 +598,7 @@ SyntaxError: Invalid or unexpected token
timeout: 5000,
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -620,7 +620,7 @@ SyntaxError: Invalid or unexpected token
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -644,7 +644,7 @@ SyntaxError: Invalid or unexpected token
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
expect(response.status).toBe(200)
@@ -657,7 +657,7 @@ describe('Function Execute API - Template Variable Edge Cases', () => {
vi.resetModules()
vi.resetAllMocks()
vi.doMock('@/lib/logs/console-logger', () => ({
vi.doMock('@/lib/logs/console/logger', () => ({
createLogger: vi.fn().mockReturnValue(mockLogger),
}))
@@ -705,7 +705,7 @@ describe('Function Execute API - Template Variable Edge Cases', () => {
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -730,7 +730,7 @@ describe('Function Execute API - Template Variable Edge Cases', () => {
},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()
@@ -752,7 +752,7 @@ describe('Function Execute API - Template Variable Edge Cases', () => {
params: {},
})
const { POST } = await import('./route')
const { POST } = await import('@/app/api/function/execute/route')
const response = await POST(req)
const data = await response.json()

View File

@@ -1,6 +1,6 @@
import { createContext, Script } from 'vm'
import { type NextRequest, NextResponse } from 'next/server'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
export const runtime = 'nodejs'

View File

@@ -2,7 +2,7 @@ import { type NextRequest, NextResponse } from 'next/server'
import { Resend } from 'resend'
import { z } from 'zod'
import { env } from '@/lib/env'
import { createLogger } from '@/lib/logs/console-logger'
import { createLogger } from '@/lib/logs/console/logger'
import { getEmailDomain } from '@/lib/urls/utils'
const resend = env.RESEND_API_KEY ? new Resend(env.RESEND_API_KEY) : null

View File

@@ -2,10 +2,13 @@ import { runs } from '@trigger.dev/sdk/v3'
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 { createLogger } from '@/lib/logs/console/logger'
import { db } from '@/db'
export const dynamic = 'force-dynamic'
import { createErrorResponse } from '@/app/api/workflows/utils'
import { apiKey as apiKeyTable } from '@/db/schema'
import { createErrorResponse } from '../../workflows/utils'
const logger = createLogger('TaskStatusAPI')

View File

@@ -3,10 +3,13 @@ import { eq, 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 { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
import { checkChunkAccess } from '@/app/api/knowledge/utils'
import { db } from '@/db'
import { document, embedding } from '@/db/schema'
import { checkChunkAccess } from '../../../../../utils'
const logger = createLogger('ChunkByIdAPI')

View File

@@ -153,7 +153,7 @@ describe('Knowledge Document Chunks API Route', () => {
})
const req = createMockRequest('POST', validChunkData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -213,7 +213,7 @@ describe('Knowledge Document Chunks API Route', () => {
})
const req = createMockRequest('POST', workflowData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -226,7 +226,7 @@ describe('Knowledge Document Chunks API Route', () => {
mockGetUserId.mockResolvedValue(null)
const req = createMockRequest('POST', validChunkData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -243,7 +243,7 @@ describe('Knowledge Document Chunks API Route', () => {
mockGetUserId.mockResolvedValue(null)
const req = createMockRequest('POST', workflowData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -262,7 +262,7 @@ describe('Knowledge Document Chunks API Route', () => {
})
const req = createMockRequest('POST', validChunkData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -281,7 +281,7 @@ describe('Knowledge Document Chunks API Route', () => {
})
const req = createMockRequest('POST', validChunkData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -303,7 +303,7 @@ describe('Knowledge Document Chunks API Route', () => {
} as any)
const req = createMockRequest('POST', validChunkData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -326,7 +326,7 @@ describe('Knowledge Document Chunks API Route', () => {
}
const req = createMockRequest('POST', invalidData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
const response = await POST(req, { params: mockParams })
const data = await response.json()
@@ -367,7 +367,7 @@ describe('Knowledge Document Chunks API Route', () => {
})
const req = createMockRequest('POST', validChunkData)
const { POST } = await import('./route')
const { POST } = await import('@/app/api/knowledge/[id]/documents/[documentId]/chunks/route')
await POST(req, { params: mockParams })
expect(mockTx.values).toHaveBeenCalled()

View File

@@ -3,7 +3,10 @@ import { and, asc, eq, ilike, inArray, 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 { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
import { estimateTokenCount } from '@/lib/tokenization/estimators'
import { getUserId } from '@/app/api/auth/oauth/utils'
import {

View File

@@ -14,7 +14,7 @@ import {
mockKnowledgeSchemas()
vi.mock('../../../utils', () => ({
vi.mock('@/app/api/knowledge/utils', () => ({
checkKnowledgeBaseAccess: vi.fn(),
checkKnowledgeBaseWriteAccess: vi.fn(),
checkDocumentAccess: vi.fn(),
@@ -98,7 +98,7 @@ describe('Document By ID API Route', () => {
const mockParams = Promise.resolve({ id: 'kb-123', documentId: 'doc-123' })
it('should retrieve document successfully for authenticated user', async () => {
const { checkDocumentAccess } = await import('../../../utils')
const { checkDocumentAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentAccess).mockResolvedValue({
@@ -108,7 +108,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await GET(req, { params: mockParams })
const data = await response.json()
@@ -123,7 +123,7 @@ describe('Document By ID API Route', () => {
mockAuth$.mockUnauthenticated()
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await GET(req, { params: mockParams })
const data = await response.json()
@@ -132,7 +132,7 @@ describe('Document By ID API Route', () => {
})
it('should return not found for non-existent document', async () => {
const { checkDocumentAccess } = await import('../../../utils')
const { checkDocumentAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentAccess).mockResolvedValue({
@@ -142,7 +142,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await GET(req, { params: mockParams })
const data = await response.json()
@@ -151,7 +151,7 @@ describe('Document By ID API Route', () => {
})
it('should return unauthorized for document without access', async () => {
const { checkDocumentAccess } = await import('../../../utils')
const { checkDocumentAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentAccess).mockResolvedValue({
@@ -160,7 +160,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await GET(req, { params: mockParams })
const data = await response.json()
@@ -169,13 +169,13 @@ describe('Document By ID API Route', () => {
})
it('should handle database errors', async () => {
const { checkDocumentAccess } = await import('../../../utils')
const { checkDocumentAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentAccess).mockRejectedValue(new Error('Database error'))
const req = createMockRequest('GET')
const { GET } = await import('./route')
const { GET } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await GET(req, { params: mockParams })
const data = await response.json()
@@ -194,7 +194,7 @@ describe('Document By ID API Route', () => {
}
it('should update document successfully', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -223,7 +223,7 @@ describe('Document By ID API Route', () => {
mockDbChain.select.mockReturnValue(selectChain)
const req = createMockRequest('PUT', validUpdateData)
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -236,7 +236,7 @@ describe('Document By ID API Route', () => {
})
it('should validate update data', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -252,7 +252,7 @@ describe('Document By ID API Route', () => {
}
const req = createMockRequest('PUT', invalidData)
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -266,7 +266,7 @@ describe('Document By ID API Route', () => {
const mockParams = Promise.resolve({ id: 'kb-123', documentId: 'doc-123' })
it('should mark document as failed due to timeout successfully', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
const processingDocument = {
...mockDocument,
@@ -303,7 +303,7 @@ describe('Document By ID API Route', () => {
mockDbChain.select.mockReturnValue(selectChain)
const req = createMockRequest('PUT', { markFailedDueToTimeout: true })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -320,7 +320,7 @@ describe('Document By ID API Route', () => {
})
it('should reject marking failed for non-processing document', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -330,7 +330,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('PUT', { markFailedDueToTimeout: true })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -339,7 +339,7 @@ describe('Document By ID API Route', () => {
})
it('should reject marking failed for recently started processing', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
const recentProcessingDocument = {
...mockDocument,
@@ -355,7 +355,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('PUT', { markFailedDueToTimeout: true })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -368,7 +368,9 @@ describe('Document By ID API Route', () => {
const mockParams = Promise.resolve({ id: 'kb-123', documentId: 'doc-123' })
it('should retry processing successfully', async () => {
const { checkDocumentWriteAccess, processDocumentAsync } = await import('../../../utils')
const { checkDocumentWriteAccess, processDocumentAsync } = await import(
'@/app/api/knowledge/utils'
)
const failedDocument = {
...mockDocument,
@@ -401,7 +403,7 @@ describe('Document By ID API Route', () => {
vi.mocked(processDocumentAsync).mockResolvedValue(undefined)
const req = createMockRequest('PUT', { retryProcessing: true })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -414,7 +416,7 @@ describe('Document By ID API Route', () => {
})
it('should reject retry for non-failed document', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -424,7 +426,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('PUT', { retryProcessing: true })
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -441,7 +443,7 @@ describe('Document By ID API Route', () => {
mockAuth$.mockUnauthenticated()
const req = createMockRequest('PUT', validUpdateData)
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -450,7 +452,7 @@ describe('Document By ID API Route', () => {
})
it('should return not found for non-existent document', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -460,7 +462,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('PUT', validUpdateData)
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -469,7 +471,7 @@ describe('Document By ID API Route', () => {
})
it('should handle database errors during update', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -480,7 +482,7 @@ describe('Document By ID API Route', () => {
mockDbChain.set.mockRejectedValue(new Error('Database error'))
const req = createMockRequest('PUT', validUpdateData)
const { PUT } = await import('./route')
const { PUT } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await PUT(req, { params: mockParams })
const data = await response.json()
@@ -493,7 +495,7 @@ describe('Document By ID API Route', () => {
const mockParams = Promise.resolve({ id: 'kb-123', documentId: 'doc-123' })
it('should delete document successfully', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -508,7 +510,7 @@ describe('Document By ID API Route', () => {
mockDbChain.where.mockResolvedValue(undefined) // Update operation resolves
const req = createMockRequest('DELETE')
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await DELETE(req, { params: mockParams })
const data = await response.json()
@@ -527,7 +529,7 @@ describe('Document By ID API Route', () => {
mockAuth$.mockUnauthenticated()
const req = createMockRequest('DELETE')
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await DELETE(req, { params: mockParams })
const data = await response.json()
@@ -536,7 +538,7 @@ describe('Document By ID API Route', () => {
})
it('should return not found for non-existent document', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -546,7 +548,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('DELETE')
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await DELETE(req, { params: mockParams })
const data = await response.json()
@@ -555,7 +557,7 @@ describe('Document By ID API Route', () => {
})
it('should return unauthorized for document without access', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -564,7 +566,7 @@ describe('Document By ID API Route', () => {
})
const req = createMockRequest('DELETE')
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await DELETE(req, { params: mockParams })
const data = await response.json()
@@ -573,7 +575,7 @@ describe('Document By ID API Route', () => {
})
it('should handle database errors during deletion', async () => {
const { checkDocumentWriteAccess } = await import('../../../utils')
const { checkDocumentWriteAccess } = await import('@/app/api/knowledge/utils')
mockAuth$.mockAuthenticatedUser()
vi.mocked(checkDocumentWriteAccess).mockResolvedValue({
@@ -584,7 +586,7 @@ describe('Document By ID API Route', () => {
mockDbChain.set.mockRejectedValue(new Error('Database error'))
const req = createMockRequest('DELETE')
const { DELETE } = await import('./route')
const { DELETE } = await import('@/app/api/knowledge/[id]/documents/[documentId]/route')
const response = await DELETE(req, { params: mockParams })
const data = await response.json()

View File

@@ -2,10 +2,17 @@ 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 { createLogger } from '@/lib/logs/console/logger'
export const dynamic = 'force-dynamic'
import {
checkDocumentAccess,
checkDocumentWriteAccess,
processDocumentAsync,
} from '@/app/api/knowledge/utils'
import { db } from '@/db'
import { document, embedding } from '@/db/schema'
import { checkDocumentAccess, checkDocumentWriteAccess, processDocumentAsync } from '../../../utils'
const logger = createLogger('DocumentByIdAPI')

Some files were not shown because too many files have changed in this diff Show More