mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-10 15:38:00 -05:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c12ddf491 | ||
|
|
27ef45f717 | ||
|
|
0414aa5f6d | ||
|
|
93f68a9092 | ||
|
|
727e5e8763 | ||
|
|
4964495abb | ||
|
|
40d3ce5e10 | ||
|
|
a251122601 | ||
|
|
9e8d2f7c7d | ||
|
|
eeb1a340b2 | ||
|
|
c91c132e88 | ||
|
|
5028930b9f | ||
|
|
b565babe1f | ||
|
|
2f57d8a884 |
123
.github/workflows/build.yml
vendored
123
.github/workflows/build.yml
vendored
@@ -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
|
||||
@@ -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 = ({
|
||||
|
||||
30
apps/docs/components/ui/video.tsx
Normal file
30
apps/docs/components/ui/video.tsx
Normal 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)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}`
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 = [
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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 })
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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) })
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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 })
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user