mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
Compare commits
1 Commits
main
...
improvemen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75b1ed304e |
@@ -9,26 +9,5 @@ Use TSDoc for documentation. No `====` separators. No non-TSDoc comments.
|
||||
## Styling
|
||||
Never update global styles. Keep all styling local to components.
|
||||
|
||||
## ID Generation
|
||||
Never use `crypto.randomUUID()`, `nanoid`, or the `uuid` package directly. Use the utilities from `@/lib/core/utils/uuid`:
|
||||
|
||||
- `generateId()` — UUID v4, use by default
|
||||
- `generateShortId(size?)` — short URL-safe ID (default 21 chars), for compact identifiers
|
||||
|
||||
Both use `crypto.getRandomValues()` under the hood and work in all contexts including non-secure (HTTP) browsers.
|
||||
|
||||
```typescript
|
||||
// ✗ Bad
|
||||
import { nanoid } from 'nanoid'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
const id = crypto.randomUUID()
|
||||
|
||||
// ✓ Good
|
||||
import { generateId, generateShortId } from '@/lib/core/utils/uuid'
|
||||
const uuid = generateId()
|
||||
const shortId = generateShortId()
|
||||
const tiny = generateShortId(8)
|
||||
```
|
||||
|
||||
## Package Manager
|
||||
Use `bun` and `bunx`, not `npm` and `npx`.
|
||||
|
||||
@@ -16,26 +16,5 @@ Use TSDoc for documentation. No `====` separators. No non-TSDoc comments.
|
||||
## Styling
|
||||
Never update global styles. Keep all styling local to components.
|
||||
|
||||
## ID Generation
|
||||
Never use `crypto.randomUUID()`, `nanoid`, or the `uuid` package directly. Use the utilities from `@/lib/core/utils/uuid`:
|
||||
|
||||
- `generateId()` — UUID v4, use by default
|
||||
- `generateShortId(size?)` — short URL-safe ID (default 21 chars), for compact identifiers
|
||||
|
||||
Both use `crypto.getRandomValues()` under the hood and work in all contexts including non-secure (HTTP) browsers.
|
||||
|
||||
```typescript
|
||||
// ✗ Bad
|
||||
import { nanoid } from 'nanoid'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
const id = crypto.randomUUID()
|
||||
|
||||
// ✓ Good
|
||||
import { generateId, generateShortId } from '@/lib/core/utils/uuid'
|
||||
const uuid = generateId()
|
||||
const shortId = generateShortId()
|
||||
const tiny = generateShortId(8)
|
||||
```
|
||||
|
||||
## Package Manager
|
||||
Use `bun` and `bunx`, not `npm` and `npx`.
|
||||
|
||||
@@ -7,7 +7,6 @@ You are a professional software engineer. All code must follow best practices: a
|
||||
- **Logging**: Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log`
|
||||
- **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments
|
||||
- **Styling**: Never update global styles. Keep all styling local to components
|
||||
- **ID Generation**: Never use `crypto.randomUUID()`, `nanoid`, or `uuid` package. Use `generateId()` (UUID v4) or `generateShortId()` (compact) from `@/lib/core/utils/uuid`
|
||||
- **Package Manager**: Use `bun` and `bunx`, not `npm` and `npx`
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -7,7 +7,6 @@ You are a professional software engineer. All code must follow best practices: a
|
||||
- **Logging**: Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log`
|
||||
- **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments
|
||||
- **Styling**: Never update global styles. Keep all styling local to components
|
||||
- **ID Generation**: Never use `crypto.randomUUID()`, `nanoid`, or `uuid` package. Use `generateId()` (UUID v4) or `generateShortId()` (compact) from `@/lib/core/utils/uuid`
|
||||
- **Package Manager**: Use `bun` and `bunx`, not `npm` and `npx`
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -1,26 +1,39 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { ArrowLeft, ChevronLeft } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
|
||||
export function BackLink() {
|
||||
const [isHovered, setIsHovered] = useState(false)
|
||||
|
||||
return (
|
||||
<Link
|
||||
href='/blog'
|
||||
className='group flex items-center gap-1 text-[var(--landing-text-muted)] text-sm hover:text-[var(--landing-text)]'
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
className='group/link inline-flex items-center gap-1.5 font-season text-[var(--landing-text-muted)] text-sm tracking-[0.02em] hover:text-[var(--landing-text)]'
|
||||
>
|
||||
<span className='group-hover:-translate-x-0.5 inline-flex transition-transform duration-200'>
|
||||
{isHovered ? (
|
||||
<ArrowLeft className='h-4 w-4' aria-hidden='true' />
|
||||
) : (
|
||||
<ChevronLeft className='h-4 w-4' aria-hidden='true' />
|
||||
)}
|
||||
</span>
|
||||
<svg
|
||||
className='h-3 w-3 shrink-0'
|
||||
viewBox='0 0 10 10'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<line
|
||||
x1='1'
|
||||
y1='5'
|
||||
x2='10'
|
||||
y2='5'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.33'
|
||||
strokeLinecap='square'
|
||||
className='origin-right scale-x-0 transition-transform duration-200 ease-out [transform-box:fill-box] group-hover/link:scale-x-100'
|
||||
/>
|
||||
<path
|
||||
d='M6.5 2L3.5 5L6.5 8'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.33'
|
||||
strokeLinecap='square'
|
||||
strokeLinejoin='miter'
|
||||
fill='none'
|
||||
className='group-hover/link:-translate-x-[30%] transition-transform duration-200 ease-out'
|
||||
/>
|
||||
</svg>
|
||||
Back to Blog
|
||||
</Link>
|
||||
)
|
||||
|
||||
@@ -2,58 +2,51 @@ import { Skeleton } from '@/components/emcn'
|
||||
|
||||
export default function BlogPostLoading() {
|
||||
return (
|
||||
<article className='w-full'>
|
||||
{/* Header area */}
|
||||
<div className='mx-auto max-w-[1450px] px-6 pt-8 sm:px-8 sm:pt-12 md:px-12 md:pt-16'>
|
||||
{/* Back link */}
|
||||
<article className='w-full bg-[var(--landing-bg)]'>
|
||||
<div className='px-5 pt-[60px] lg:px-16 lg:pt-[100px]'>
|
||||
<div className='mb-6'>
|
||||
<Skeleton className='h-[16px] w-[60px] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[100px] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
{/* Image + title row */}
|
||||
<div className='flex flex-col gap-8 md:flex-row md:gap-12'>
|
||||
{/* Image */}
|
||||
<div className='w-full flex-shrink-0 md:w-[450px]'>
|
||||
<Skeleton className='aspect-[450/360] w-full rounded-lg bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='aspect-[450/360] w-full rounded-[5px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
{/* Title + author */}
|
||||
<div className='flex flex-1 flex-col justify-between'>
|
||||
<div>
|
||||
<Skeleton className='h-[48px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='mt-2 h-[48px] w-[80%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[44px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='mt-2 h-[44px] w-[80%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='mt-4 h-[18px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='mt-2 h-[18px] w-[70%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
<div className='mt-4 flex items-center justify-between'>
|
||||
<div className='mt-6 flex items-center gap-6'>
|
||||
<Skeleton className='h-[12px] w-[100px] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<div className='flex items-center gap-2'>
|
||||
<Skeleton className='h-[24px] w-[24px] rounded-full bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[100px] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[20px] w-[20px] rounded-full bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[12px] w-[80px] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
<Skeleton className='h-[32px] w-[32px] rounded-[6px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Divider */}
|
||||
<Skeleton className='mt-8 h-[1px] w-full bg-[var(--landing-bg-elevated)] sm:mt-12' />
|
||||
{/* Date + description */}
|
||||
<div className='flex flex-col gap-6 py-8 sm:flex-row sm:items-start sm:justify-between sm:gap-8 sm:py-10'>
|
||||
<Skeleton className='h-[16px] w-[120px] flex-shrink-0 rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<div className='flex-1 space-y-2'>
|
||||
<Skeleton className='h-[20px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[20px] w-[70%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
|
||||
<div className='mt-8 h-px w-full bg-[var(--landing-bg-elevated)]' />
|
||||
|
||||
<div className='mx-5 border-[var(--landing-bg-elevated)] border-x lg:mx-16'>
|
||||
<div className='mx-auto max-w-[900px] px-6 py-16'>
|
||||
<div className='space-y-4'>
|
||||
<Skeleton className='h-[16px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[95%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[88%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='mt-6 h-[24px] w-[200px] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[92%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[85%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Article body */}
|
||||
<div className='mx-auto max-w-[900px] px-6 pb-20 sm:px-8 md:px-12'>
|
||||
<div className='space-y-4'>
|
||||
<Skeleton className='h-[16px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[95%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[88%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='mt-6 h-[24px] w-[200px] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-full rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[92%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
<Skeleton className='h-[16px] w-[85%] rounded-[4px] bg-[var(--landing-bg-elevated)]' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='-mt-px h-px w-full bg-[var(--landing-bg-elevated)]' />
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import Link from 'next/link'
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/emcn'
|
||||
import { FAQ } from '@/lib/blog/faq'
|
||||
import { getAllPostMeta, getPostBySlug, getRelatedPosts } from '@/lib/blog/registry'
|
||||
import { buildArticleJsonLd, buildBreadcrumbJsonLd, buildPostMetadata } from '@/lib/blog/seo'
|
||||
import { buildPostGraphJsonLd, buildPostMetadata } from '@/lib/blog/seo'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { BackLink } from '@/app/(landing)/blog/[slug]/back-link'
|
||||
import { ShareButton } from '@/app/(landing)/blog/[slug]/share-button'
|
||||
@@ -30,27 +30,27 @@ export default async function Page({ params }: { params: Promise<{ slug: string
|
||||
const { slug } = await params
|
||||
const post = await getPostBySlug(slug)
|
||||
const Article = post.Content
|
||||
const jsonLd = buildArticleJsonLd(post)
|
||||
const breadcrumbLd = buildBreadcrumbJsonLd(post)
|
||||
const graphJsonLd = buildPostGraphJsonLd(post)
|
||||
const related = await getRelatedPosts(slug, 3)
|
||||
|
||||
return (
|
||||
<article className='w-full' itemScope itemType='https://schema.org/BlogPosting'>
|
||||
<article
|
||||
className='w-full bg-[var(--landing-bg)]'
|
||||
itemScope
|
||||
itemType='https://schema.org/TechArticle'
|
||||
>
|
||||
<script
|
||||
type='application/ld+json'
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(graphJsonLd) }}
|
||||
/>
|
||||
<script
|
||||
type='application/ld+json'
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbLd) }}
|
||||
/>
|
||||
<header className='mx-auto max-w-[1450px] px-6 pt-8 sm:px-8 sm:pt-12 md:px-12 md:pt-16'>
|
||||
<header className='px-5 pt-[60px] lg:px-16 lg:pt-[100px]'>
|
||||
<div className='mb-6'>
|
||||
<BackLink />
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-8 md:flex-row md:gap-12'>
|
||||
<div className='w-full flex-shrink-0 md:w-[450px]'>
|
||||
<div className='relative w-full overflow-hidden rounded-lg'>
|
||||
<div className='relative w-full overflow-hidden rounded-[5px]'>
|
||||
<Image
|
||||
src={post.ogImage}
|
||||
alt={post.title}
|
||||
@@ -65,18 +65,35 @@ export default async function Page({ params }: { params: Promise<{ slug: string
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-1 flex-col justify-between'>
|
||||
<h1
|
||||
className='text-balance font-[500] text-[36px] text-[var(--landing-text)] leading-tight tracking-tight sm:text-[48px] md:text-[56px] lg:text-[64px]'
|
||||
itemProp='headline'
|
||||
>
|
||||
{post.title}
|
||||
</h1>
|
||||
<div className='mt-4 flex items-center justify-between'>
|
||||
<div>
|
||||
<h1
|
||||
className='text-balance font-[430] font-season text-[28px] text-white leading-[110%] tracking-[-0.02em] sm:text-[36px] md:text-[44px] lg:text-[52px]'
|
||||
itemProp='headline'
|
||||
>
|
||||
{post.title}
|
||||
</h1>
|
||||
<p className='mt-4 font-[430] font-season text-[var(--landing-text-body)] text-base leading-[150%] tracking-[0.02em] sm:text-lg'>
|
||||
{post.description}
|
||||
</p>
|
||||
</div>
|
||||
<div className='mt-6 flex items-center gap-6'>
|
||||
<time
|
||||
className='font-martian-mono text-[var(--landing-text-subtle)] text-xs uppercase tracking-[0.1em]'
|
||||
dateTime={post.date}
|
||||
itemProp='datePublished'
|
||||
>
|
||||
{new Date(post.date).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
})}
|
||||
</time>
|
||||
<meta itemProp='dateModified' content={post.updated ?? post.date} />
|
||||
<div className='flex items-center gap-3'>
|
||||
{(post.authors || [post.author]).map((a, idx) => (
|
||||
<div key={idx} className='flex items-center gap-2'>
|
||||
{a?.avatarUrl ? (
|
||||
<Avatar className='size-6'>
|
||||
<Avatar className='size-5'>
|
||||
<AvatarImage src={a.avatarUrl} alt={a.name} />
|
||||
<AvatarFallback>{a.name.slice(0, 2)}</AvatarFallback>
|
||||
</Avatar>
|
||||
@@ -85,7 +102,7 @@ export default async function Page({ params }: { params: Promise<{ slug: string
|
||||
href={a?.url || '#'}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer author'
|
||||
className='text-[var(--landing-text-muted)] text-sm leading-[1.5] hover:text-[var(--landing-text)] sm:text-md'
|
||||
className='font-martian-mono text-[var(--landing-text-muted)] text-xs uppercase tracking-[0.1em] hover:text-white'
|
||||
itemProp='author'
|
||||
itemScope
|
||||
itemType='https://schema.org/Person'
|
||||
@@ -95,78 +112,72 @@ export default async function Page({ params }: { params: Promise<{ slug: string
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<ShareButton url={`${getBaseUrl()}/blog/${slug}`} title={post.title} />
|
||||
<div className='ml-auto'>
|
||||
<ShareButton url={`${getBaseUrl()}/blog/${slug}`} title={post.title} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr className='mt-8 border-[var(--landing-bg-elevated)] border-t sm:mt-12' />
|
||||
<div className='flex flex-col gap-6 py-8 sm:flex-row sm:items-start sm:justify-between sm:gap-8 sm:py-10'>
|
||||
<div className='flex flex-shrink-0 items-center gap-4'>
|
||||
<time
|
||||
className='block text-[var(--landing-text-muted)] text-sm leading-[1.5] sm:text-md'
|
||||
dateTime={post.date}
|
||||
itemProp='datePublished'
|
||||
>
|
||||
{new Date(post.date).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
})}
|
||||
</time>
|
||||
<meta itemProp='dateModified' content={post.updated ?? post.date} />
|
||||
</div>
|
||||
<div className='flex-1'>
|
||||
<p className='m-0 block translate-y-[-4px] font-[400] text-[var(--landing-text-muted)] text-lg leading-[1.5] sm:text-[20px] md:text-[26px]'>
|
||||
{post.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className='mx-auto max-w-[900px] px-6 pb-20 sm:px-8 md:px-12' itemProp='articleBody'>
|
||||
<div className='prose prose-lg prose-invert max-w-none prose-blockquote:border-[var(--landing-border-strong)] prose-hr:border-[var(--landing-bg-elevated)] prose-a:text-[var(--landing-text)] prose-blockquote:text-[var(--landing-text-muted)] prose-code:text-[var(--landing-text)] prose-headings:text-[var(--landing-text)] prose-li:text-[var(--landing-text-muted)] prose-p:text-[var(--landing-text-muted)] prose-strong:text-[var(--landing-text)]'>
|
||||
<Article />
|
||||
{post.faq && post.faq.length > 0 ? <FAQ items={post.faq} /> : null}
|
||||
</div>
|
||||
</div>
|
||||
{related.length > 0 && (
|
||||
<div className='mx-auto max-w-[900px] px-6 pb-24 sm:px-8 md:px-12'>
|
||||
<h2 className='mb-4 font-[500] text-[24px] text-[var(--landing-text)]'>Related posts</h2>
|
||||
<div className='grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-6 lg:grid-cols-3'>
|
||||
{related.map((p) => (
|
||||
<Link key={p.slug} href={`/blog/${p.slug}`} className='group'>
|
||||
<div className='overflow-hidden rounded-lg border border-[var(--landing-bg-elevated)]'>
|
||||
<Image
|
||||
src={p.ogImage}
|
||||
alt={p.title}
|
||||
width={600}
|
||||
height={315}
|
||||
className='h-[160px] w-full object-cover'
|
||||
sizes='(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw'
|
||||
loading='lazy'
|
||||
unoptimized
|
||||
/>
|
||||
<div className='p-3'>
|
||||
<div className='mb-1 text-[var(--landing-text-muted)] text-xs'>
|
||||
{new Date(p.date).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
})}
|
||||
</div>
|
||||
<div className='font-[500] text-[var(--landing-text)] text-sm leading-tight'>
|
||||
{p.title}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
<div className='mt-8 h-px w-full bg-[var(--landing-bg-elevated)]' />
|
||||
|
||||
<div className='mx-5 border-[var(--landing-bg-elevated)] border-x lg:mx-16'>
|
||||
<div className='mx-auto max-w-[900px] px-6 py-16' itemProp='articleBody'>
|
||||
<div className='prose prose-lg prose-invert max-w-none prose-blockquote:border-[var(--landing-border-strong)] prose-hr:border-[var(--landing-bg-elevated)] prose-headings:font-[430] prose-headings:font-season prose-a:text-white prose-blockquote:text-[var(--landing-text-muted)] prose-code:text-white prose-headings:text-white prose-li:text-[var(--landing-text-body)] prose-p:text-[var(--landing-text-body)] prose-strong:text-white prose-headings:tracking-[-0.02em]'>
|
||||
<Article />
|
||||
{post.faq && post.faq.length > 0 ? <FAQ items={post.faq} /> : null}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{related.length > 0 && (
|
||||
<>
|
||||
<div className='h-px w-full bg-[var(--landing-bg-elevated)]' />
|
||||
<nav aria-label='Related posts' className='flex'>
|
||||
{related.map((p) => (
|
||||
<Link
|
||||
key={p.slug}
|
||||
href={`/blog/${p.slug}`}
|
||||
className='group flex flex-1 flex-col gap-4 border-[var(--landing-bg-elevated)] p-6 transition-colors hover:bg-[var(--landing-bg-elevated)] md:border-l md:first:border-l-0'
|
||||
>
|
||||
<div className='relative aspect-video w-full overflow-hidden rounded-[5px]'>
|
||||
<Image
|
||||
src={p.ogImage}
|
||||
alt={p.title}
|
||||
fill
|
||||
sizes='(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw'
|
||||
className='object-cover'
|
||||
loading='lazy'
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-col gap-2'>
|
||||
<span className='font-martian-mono text-[var(--landing-text-subtle)] text-xs uppercase tracking-[0.1em]'>
|
||||
{new Date(p.date).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
year: '2-digit',
|
||||
})}
|
||||
</span>
|
||||
<h3 className='font-[430] font-season text-lg text-white leading-tight tracking-[-0.01em]'>
|
||||
{p.title}
|
||||
</h3>
|
||||
<p className='line-clamp-2 text-[var(--landing-text-muted)] text-sm leading-[150%]'>
|
||||
{p.description}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='-mt-px h-px w-full bg-[var(--landing-bg-elevated)]' />
|
||||
|
||||
<meta itemProp='publisher' content='Sim' />
|
||||
<meta itemProp='inLanguage' content='en-US' />
|
||||
<meta itemProp='keywords' content={post.tags.join(', ')} />
|
||||
{post.wordCount && <meta itemProp='wordCount' content={String(post.wordCount)} />}
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,29 @@ export async function generateMetadata({
|
||||
const { id } = await params
|
||||
const posts = (await getAllPostMeta()).filter((p) => p.author.id === id)
|
||||
const author = posts[0]?.author
|
||||
return { title: author?.name ?? 'Author' }
|
||||
const name = author?.name ?? 'Author'
|
||||
return {
|
||||
title: `${name} — Sim Blog`,
|
||||
description: `Read articles by ${name} on the Sim blog.`,
|
||||
alternates: { canonical: `https://sim.ai/blog/authors/${id}` },
|
||||
openGraph: {
|
||||
title: `${name} — Sim Blog`,
|
||||
description: `Read articles by ${name} on the Sim blog.`,
|
||||
url: `https://sim.ai/blog/authors/${id}`,
|
||||
siteName: 'Sim',
|
||||
type: 'profile',
|
||||
...(author?.avatarUrl
|
||||
? { images: [{ url: author.avatarUrl, width: 400, height: 400, alt: name }] }
|
||||
: {}),
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary',
|
||||
title: `${name} — Sim Blog`,
|
||||
description: `Read articles by ${name} on the Sim blog.`,
|
||||
site: '@simdotai',
|
||||
...(author?.xHandle ? { creator: `@${author.xHandle}` } : {}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default async function AuthorPage({ params }: { params: Promise<{ id: string }> }) {
|
||||
@@ -27,19 +49,41 @@ export default async function AuthorPage({ params }: { params: Promise<{ id: str
|
||||
</main>
|
||||
)
|
||||
}
|
||||
const personJsonLd = {
|
||||
const graphJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Person',
|
||||
name: author.name,
|
||||
url: `https://sim.ai/blog/authors/${author.id}`,
|
||||
sameAs: author.url ? [author.url] : [],
|
||||
image: author.avatarUrl,
|
||||
'@graph': [
|
||||
{
|
||||
'@type': 'Person',
|
||||
name: author.name,
|
||||
url: `https://sim.ai/blog/authors/${author.id}`,
|
||||
sameAs: author.url ? [author.url] : [],
|
||||
image: author.avatarUrl,
|
||||
worksFor: {
|
||||
'@type': 'Organization',
|
||||
name: 'Sim',
|
||||
url: 'https://sim.ai',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'BreadcrumbList',
|
||||
itemListElement: [
|
||||
{ '@type': 'ListItem', position: 1, name: 'Home', item: 'https://sim.ai' },
|
||||
{ '@type': 'ListItem', position: 2, name: 'Blog', item: 'https://sim.ai/blog' },
|
||||
{
|
||||
'@type': 'ListItem',
|
||||
position: 3,
|
||||
name: author.name,
|
||||
item: `https://sim.ai/blog/authors/${author.id}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
return (
|
||||
<main className='mx-auto max-w-[900px] px-6 py-10 sm:px-8 md:px-12'>
|
||||
<script
|
||||
type='application/ld+json'
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(personJsonLd) }}
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(graphJsonLd) }}
|
||||
/>
|
||||
<div className='mb-6 flex items-center gap-3'>
|
||||
{author.avatarUrl ? (
|
||||
|
||||
@@ -9,8 +9,14 @@ export default async function StudioLayout({ children }: { children: React.React
|
||||
'@type': 'Organization',
|
||||
name: 'Sim',
|
||||
url: 'https://sim.ai',
|
||||
description:
|
||||
'Sim is an open-source platform for building, testing, and deploying AI agent workflows.',
|
||||
logo: 'https://sim.ai/logo/primary/small.png',
|
||||
sameAs: ['https://x.com/simdotai'],
|
||||
sameAs: [
|
||||
'https://x.com/simdotai',
|
||||
'https://github.com/simstudioai/sim',
|
||||
'https://www.linkedin.com/company/simdotai',
|
||||
],
|
||||
}
|
||||
|
||||
const websiteJsonLd = {
|
||||
@@ -18,11 +24,6 @@ export default async function StudioLayout({ children }: { children: React.React
|
||||
'@type': 'WebSite',
|
||||
name: 'Sim',
|
||||
url: 'https://sim.ai',
|
||||
potentialAction: {
|
||||
'@type': 'SearchAction',
|
||||
target: 'https://sim.ai/search?q={search_term_string}',
|
||||
'query-input': 'required name=search_term_string',
|
||||
},
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,60 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { Badge } from '@/components/emcn'
|
||||
import { getAllPostMeta } from '@/lib/blog/registry'
|
||||
import { buildCollectionPageJsonLd } from '@/lib/blog/seo'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Blog',
|
||||
description: 'Announcements, insights, and guides from the Sim team.',
|
||||
export async function generateMetadata({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: Promise<{ page?: string; tag?: string }>
|
||||
}): Promise<Metadata> {
|
||||
const { page, tag } = await searchParams
|
||||
const pageNum = Math.max(1, Number(page || 1))
|
||||
|
||||
const titleParts = ['Blog']
|
||||
if (tag) titleParts.push(tag)
|
||||
if (pageNum > 1) titleParts.push(`Page ${pageNum}`)
|
||||
const title = titleParts.join(' — ')
|
||||
|
||||
const description = tag
|
||||
? `Sim blog posts tagged "${tag}" — insights and guides for building AI agent workflows.`
|
||||
: 'Announcements, insights, and guides for building AI agent workflows.'
|
||||
|
||||
const canonicalParams = new URLSearchParams()
|
||||
if (tag) canonicalParams.set('tag', tag)
|
||||
if (pageNum > 1) canonicalParams.set('page', String(pageNum))
|
||||
const qs = canonicalParams.toString()
|
||||
const canonical = `https://sim.ai/blog${qs ? `?${qs}` : ''}`
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
alternates: { canonical },
|
||||
openGraph: {
|
||||
title: `${title} | Sim`,
|
||||
description,
|
||||
url: canonical,
|
||||
siteName: 'Sim',
|
||||
locale: 'en_US',
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: 'https://sim.ai/logo/primary/medium.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'Sim Blog',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: `${title} | Sim`,
|
||||
description,
|
||||
site: '@simdotai',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const revalidate = 3600
|
||||
@@ -37,19 +86,13 @@ export default async function BlogIndex({
|
||||
const featured = pageNum === 1 ? posts.slice(0, 3) : []
|
||||
const remaining = pageNum === 1 ? posts.slice(3) : posts
|
||||
|
||||
const blogJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Blog',
|
||||
name: 'Sim Blog',
|
||||
url: 'https://sim.ai/blog',
|
||||
description: 'Announcements, insights, and guides for building AI agent workflows.',
|
||||
}
|
||||
const collectionJsonLd = buildCollectionPageJsonLd()
|
||||
|
||||
return (
|
||||
<section className='bg-[var(--landing-bg)]'>
|
||||
<script
|
||||
type='application/ld+json'
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(blogJsonLd) }}
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(collectionJsonLd) }}
|
||||
/>
|
||||
|
||||
{/* Section header */}
|
||||
@@ -81,7 +124,7 @@ export default async function BlogIndex({
|
||||
{/* Featured posts */}
|
||||
{featured.length > 0 && (
|
||||
<>
|
||||
<div className='flex'>
|
||||
<nav aria-label='Featured posts' className='flex'>
|
||||
{featured.map((p, index) => (
|
||||
<Link
|
||||
key={p.slug}
|
||||
@@ -89,11 +132,14 @@ export default async function BlogIndex({
|
||||
className='group flex flex-1 flex-col gap-4 border-[var(--landing-bg-elevated)] p-6 transition-colors hover:bg-[var(--landing-bg-elevated)] md:border-l md:first:border-l-0'
|
||||
>
|
||||
<div className='relative aspect-video w-full overflow-hidden rounded-[5px]'>
|
||||
<img
|
||||
<Image
|
||||
src={p.ogImage}
|
||||
alt={p.title}
|
||||
className='h-full w-full object-cover'
|
||||
loading={index < 3 ? 'eager' : 'lazy'}
|
||||
fill
|
||||
sizes='(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw'
|
||||
className='object-cover'
|
||||
priority={index < 3}
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-col gap-2'>
|
||||
@@ -112,7 +158,7 @@ export default async function BlogIndex({
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div className='h-px w-full bg-[var(--landing-bg-elevated)]' />
|
||||
</>
|
||||
@@ -151,12 +197,14 @@ export default async function BlogIndex({
|
||||
</div>
|
||||
|
||||
{/* Image */}
|
||||
<div className='hidden h-[80px] w-[140px] shrink-0 overflow-hidden rounded-[5px] sm:block'>
|
||||
<img
|
||||
<div className='relative hidden h-[80px] w-[140px] shrink-0 overflow-hidden rounded-[5px] sm:block'>
|
||||
<Image
|
||||
src={p.ogImage}
|
||||
alt={p.title}
|
||||
className='h-full w-full object-cover'
|
||||
loading='lazy'
|
||||
fill
|
||||
sizes='140px'
|
||||
className='object-cover'
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
@@ -166,11 +214,12 @@ export default async function BlogIndex({
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<div className='px-6 py-8'>
|
||||
<nav aria-label='Pagination' className='px-6 py-8'>
|
||||
<div className='flex items-center justify-center gap-3'>
|
||||
{pageNum > 1 && (
|
||||
<Link
|
||||
href={`/blog?page=${pageNum - 1}${tag ? `&tag=${encodeURIComponent(tag)}` : ''}`}
|
||||
rel='prev'
|
||||
className='rounded-[5px] border border-[var(--landing-border-strong)] px-3 py-1 text-[var(--landing-text)] text-sm transition-colors hover:bg-[var(--landing-bg-elevated)]'
|
||||
>
|
||||
Previous
|
||||
@@ -182,13 +231,14 @@ export default async function BlogIndex({
|
||||
{pageNum < totalPages && (
|
||||
<Link
|
||||
href={`/blog?page=${pageNum + 1}${tag ? `&tag=${encodeURIComponent(tag)}` : ''}`}
|
||||
rel='next'
|
||||
className='rounded-[5px] border border-[var(--landing-border-strong)] px-3 py-1 text-[var(--landing-text)] text-sm transition-colors hover:bg-[var(--landing-bg-elevated)]'
|
||||
>
|
||||
Next
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,13 +7,18 @@ export async function GET() {
|
||||
const posts = await getAllPostMeta()
|
||||
const items = posts.slice(0, 50)
|
||||
const site = 'https://sim.ai'
|
||||
const lastBuildDate =
|
||||
items.length > 0 ? new Date(items[0].date).toUTCString() : new Date().toUTCString()
|
||||
|
||||
const xml = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<rss version="2.0">
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Sim Blog</title>
|
||||
<link>${site}</link>
|
||||
<description>Announcements, insights, and guides for AI agent workflows.</description>
|
||||
<language>en-us</language>
|
||||
<lastBuildDate>${lastBuildDate}</lastBuildDate>
|
||||
<atom:link href="${site}/blog/rss.xml" rel="self" type="application/rss+xml" />
|
||||
${items
|
||||
.map(
|
||||
(p) => `
|
||||
@@ -26,6 +31,7 @@ export async function GET() {
|
||||
${(p.authors || [p.author])
|
||||
.map((a) => `<author><![CDATA[${a.name}${a.url ? ` (${a.url})` : ''}]]></author>`)
|
||||
.join('\n')}
|
||||
${p.tags.map((t) => `<category><![CDATA[${t}]]></category>`).join('\n ')}
|
||||
</item>`
|
||||
)
|
||||
.join('')}
|
||||
|
||||
@@ -4,12 +4,42 @@ import { getAllTags } from '@/lib/blog/registry'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Tags',
|
||||
description: 'Browse Sim blog posts by topic — AI agents, workflows, integrations, and more.',
|
||||
alternates: { canonical: 'https://sim.ai/blog/tags' },
|
||||
openGraph: {
|
||||
title: 'Blog Tags | Sim',
|
||||
description: 'Browse Sim blog posts by topic — AI agents, workflows, integrations, and more.',
|
||||
url: 'https://sim.ai/blog/tags',
|
||||
siteName: 'Sim',
|
||||
locale: 'en_US',
|
||||
type: 'website',
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary',
|
||||
title: 'Blog Tags | Sim',
|
||||
description: 'Browse Sim blog posts by topic — AI agents, workflows, integrations, and more.',
|
||||
site: '@simdotai',
|
||||
},
|
||||
}
|
||||
|
||||
const breadcrumbJsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BreadcrumbList',
|
||||
itemListElement: [
|
||||
{ '@type': 'ListItem', position: 1, name: 'Home', item: 'https://sim.ai' },
|
||||
{ '@type': 'ListItem', position: 2, name: 'Blog', item: 'https://sim.ai/blog' },
|
||||
{ '@type': 'ListItem', position: 3, name: 'Tags', item: 'https://sim.ai/blog/tags' },
|
||||
],
|
||||
}
|
||||
|
||||
export default async function TagsIndex() {
|
||||
const tags = await getAllTags()
|
||||
return (
|
||||
<main className='mx-auto max-w-[900px] px-6 py-10 sm:px-8 md:px-12'>
|
||||
<script
|
||||
type='application/ld+json'
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
|
||||
/>
|
||||
<h1 className='mb-6 font-[500] text-[32px] text-[var(--landing-text)] leading-tight'>
|
||||
Browse by tag
|
||||
</h1>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getFormattedGitHubStars } from '@/app/(landing)/actions/github'
|
||||
|
||||
const logger = createLogger('github-stars')
|
||||
|
||||
const INITIAL_STARS = '27k'
|
||||
const INITIAL_STARS = '27.6k'
|
||||
|
||||
/**
|
||||
* Client component that displays GitHub stars count.
|
||||
|
||||
@@ -9,11 +9,11 @@ import { a2aAgent, workflow } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq, isNull, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { generateSkillsFromWorkflow } from '@/lib/a2a/agent-card'
|
||||
import { A2A_DEFAULT_CAPABILITIES } from '@/lib/a2a/constants'
|
||||
import { sanitizeAgentName } from '@/lib/a2a/utils'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { captureServerEvent } from '@/lib/posthog/server'
|
||||
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/persistence/utils'
|
||||
import { hasValidStartBlockInState } from '@/lib/workflows/triggers/trigger-utils'
|
||||
@@ -173,7 +173,7 @@ export async function POST(request: NextRequest) {
|
||||
skillTags
|
||||
)
|
||||
|
||||
const agentId = generateId()
|
||||
const agentId = uuidv4()
|
||||
const agentName = name || sanitizeAgentName(wf.name)
|
||||
|
||||
const [agent] = await db
|
||||
|
||||
@@ -4,6 +4,7 @@ import { a2aAgent, a2aPushNotificationConfig, a2aTask, workflow } from '@sim/db/
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { A2A_DEFAULT_TIMEOUT, A2A_MAX_HISTORY_LENGTH } from '@/lib/a2a/constants'
|
||||
import { notifyTaskStateChange } from '@/lib/a2a/push-notifications'
|
||||
import {
|
||||
@@ -17,7 +18,6 @@ import { acquireLock, getRedisClient, releaseLock } from '@/lib/core/config/redi
|
||||
import { validateUrlWithDNS } from '@/lib/core/security/input-validation.server'
|
||||
import { SSE_HEADERS } from '@/lib/core/utils/sse'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { markExecutionCancelled } from '@/lib/execution/cancellation'
|
||||
import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
|
||||
import { getWorkspaceBilledAccountUserId } from '@/lib/workspaces/utils'
|
||||
@@ -400,11 +400,11 @@ async function handleMessageSend(
|
||||
|
||||
const message = params.message
|
||||
const taskId = message.taskId || generateTaskId()
|
||||
const contextId = message.contextId || generateId()
|
||||
const contextId = message.contextId || uuidv4()
|
||||
|
||||
// Distributed lock to prevent concurrent task processing
|
||||
const lockKey = `a2a:task:${taskId}:lock`
|
||||
const lockValue = generateId()
|
||||
const lockValue = uuidv4()
|
||||
const acquired = await acquireLock(lockKey, lockValue, 60)
|
||||
|
||||
if (!acquired) {
|
||||
@@ -628,12 +628,12 @@ async function handleMessageStream(
|
||||
}
|
||||
|
||||
const message = params.message
|
||||
const contextId = message.contextId || generateId()
|
||||
const contextId = message.contextId || uuidv4()
|
||||
const taskId = message.taskId || generateTaskId()
|
||||
|
||||
// Distributed lock to prevent concurrent task processing
|
||||
const lockKey = `a2a:task:${taskId}:lock`
|
||||
const lockValue = generateId()
|
||||
const lockValue = uuidv4()
|
||||
const acquired = await acquireLock(lockKey, lockValue, 300)
|
||||
|
||||
if (!acquired) {
|
||||
@@ -1427,7 +1427,7 @@ async function handlePushNotificationSet(
|
||||
.where(eq(a2aPushNotificationConfig.id, existingConfig.id))
|
||||
} else {
|
||||
await db.insert(a2aPushNotificationConfig).values({
|
||||
id: generateId(),
|
||||
id: uuidv4(),
|
||||
taskId: params.id,
|
||||
url: config.url,
|
||||
token: config.token || null,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Artifact, Message, PushNotificationConfig, Task, TaskState } from '@a2a-js/sdk'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { generateInternalToken } from '@/lib/auth/internal'
|
||||
import { getInternalApiBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
/** A2A v0.3 JSON-RPC method names */
|
||||
export const A2A_METHODS = {
|
||||
@@ -85,7 +85,7 @@ export function isJSONRPCRequest(obj: unknown): obj is JSONRPCRequest {
|
||||
}
|
||||
|
||||
export function generateTaskId(): string {
|
||||
return generateId()
|
||||
return uuidv4()
|
||||
}
|
||||
|
||||
export function createTaskStatus(state: TaskState): { state: TaskState; timestamp: string } {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { db } from '@sim/db'
|
||||
import { academyCertificate, user } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getCourseById } from '@/lib/academy/content'
|
||||
@@ -9,7 +10,6 @@ import type { CertificateMetadata } from '@/lib/academy/types'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import type { TokenBucketConfig } from '@/lib/core/rate-limiter'
|
||||
import { RateLimiter } from '@/lib/core/rate-limiter'
|
||||
import { generateShortId } from '@/lib/core/utils/uuid'
|
||||
|
||||
const logger = createLogger('AcademyCertificatesAPI')
|
||||
|
||||
@@ -106,7 +106,7 @@ export async function POST(req: NextRequest) {
|
||||
const [certificate] = await db
|
||||
.insert(academyCertificate)
|
||||
.values({
|
||||
id: generateShortId(),
|
||||
id: nanoid(),
|
||||
userId: session.user.id,
|
||||
courseId,
|
||||
status: 'active',
|
||||
@@ -211,5 +211,5 @@ export async function GET(req: NextRequest) {
|
||||
/** Generates a human-readable certificate number, e.g. SIM-2026-A3K9XZ2P */
|
||||
function generateCertificateNumber(): string {
|
||||
const year = new Date().getFullYear()
|
||||
return `SIM-${year}-${generateShortId(8).toUpperCase()}`
|
||||
return `SIM-${year}-${nanoid(8).toUpperCase()}`
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { env } from '@/lib/core/config/env'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
const logger = createLogger('ShopifyAuthorize')
|
||||
|
||||
@@ -162,7 +161,7 @@ export async function GET(request: NextRequest) {
|
||||
const baseUrl = getBaseUrl()
|
||||
const redirectUri = `${baseUrl}/api/auth/oauth2/callback/shopify`
|
||||
|
||||
const state = generateId()
|
||||
const state = crypto.randomUUID()
|
||||
|
||||
const oauthUrl =
|
||||
`https://${cleanShop}/admin/oauth/authorize?` +
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { randomInt } from 'crypto'
|
||||
import { randomInt, randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { chat, verification } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -10,7 +10,6 @@ import { getRedisClient } from '@/lib/core/config/redis'
|
||||
import { addCorsHeaders, isEmailAllowed } from '@/lib/core/security/deployment'
|
||||
import { getStorageMethod } from '@/lib/core/storage'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { sendEmail } from '@/lib/messaging/email/mailer'
|
||||
import { setChatAuthCookie } from '@/app/api/chat/utils'
|
||||
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
|
||||
@@ -62,7 +61,7 @@ async function storeOTP(email: string, chatId: string, otp: string): Promise<voi
|
||||
await db.transaction(async (tx) => {
|
||||
await tx.delete(verification).where(eq(verification.identifier, identifier))
|
||||
await tx.insert(verification).values({
|
||||
id: generateId(),
|
||||
id: randomUUID(),
|
||||
identifier,
|
||||
value,
|
||||
expiresAt,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { chat, workflow } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -6,7 +7,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { addCorsHeaders, validateAuthToken } from '@/lib/core/security/deployment'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { preprocessExecution } from '@/lib/execution/preprocessing'
|
||||
import { LoggingSession } from '@/lib/logs/execution/logging-session'
|
||||
import { ChatFiles } from '@/lib/uploads'
|
||||
@@ -103,7 +103,7 @@ export async function POST(
|
||||
)
|
||||
}
|
||||
|
||||
const executionId = generateId()
|
||||
const executionId = randomUUID()
|
||||
const loggingSession = new LoggingSession(
|
||||
deployment.workflowId,
|
||||
executionId,
|
||||
@@ -150,7 +150,7 @@ export async function POST(
|
||||
return addCorsHeaders(createErrorResponse('No input provided', 400), request)
|
||||
}
|
||||
|
||||
const executionId = generateId()
|
||||
const executionId = randomUUID()
|
||||
|
||||
const loggingSession = new LoggingSession(deployment.workflowId, executionId, 'chat', requestId)
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
createRequestTracker,
|
||||
createUnauthorizedResponse,
|
||||
} from '@/lib/copilot/request-helpers'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { captureServerEvent } from '@/lib/posthog/server'
|
||||
import {
|
||||
authorizeWorkflowByWorkspacePermission,
|
||||
@@ -206,7 +205,7 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
)
|
||||
|
||||
const userMessageIdToUse = userMessageId || generateId()
|
||||
const userMessageIdToUse = userMessageId || crypto.randomUUID()
|
||||
const reqLogger = logger.withMetadata({
|
||||
requestId: tracker.requestId,
|
||||
messageId: userMessageIdToUse,
|
||||
@@ -407,8 +406,8 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
if (stream) {
|
||||
const executionId = generateId()
|
||||
const runId = generateId()
|
||||
const executionId = crypto.randomUUID()
|
||||
const runId = crypto.randomUUID()
|
||||
const sseStream = createSSEStream({
|
||||
requestPayload,
|
||||
userId: authenticatedUserId,
|
||||
@@ -438,7 +437,7 @@ export async function POST(req: NextRequest) {
|
||||
if (!result.success) return
|
||||
|
||||
const assistantMessage: Record<string, unknown> = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
role: 'assistant' as const,
|
||||
content: result.content,
|
||||
timestamp: new Date().toISOString(),
|
||||
@@ -516,8 +515,8 @@ export async function POST(req: NextRequest) {
|
||||
return new Response(sseStream, { headers: SSE_RESPONSE_HEADERS })
|
||||
}
|
||||
|
||||
const nsExecutionId = generateId()
|
||||
const nsRunId = generateId()
|
||||
const nsExecutionId = crypto.randomUUID()
|
||||
const nsRunId = crypto.randomUUID()
|
||||
|
||||
if (actualChatId) {
|
||||
await createRunSegment({
|
||||
@@ -577,7 +576,7 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
const assistantMessage = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
role: 'assistant',
|
||||
content: responseData.content,
|
||||
timestamp: new Date().toISOString(),
|
||||
|
||||
@@ -3,10 +3,10 @@ import { member, templateCreators } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq, or } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import type { CreatorProfileDetails } from '@/app/_types/creator-profile'
|
||||
|
||||
const logger = createLogger('CreatorProfilesAPI')
|
||||
@@ -147,7 +147,7 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Create the profile
|
||||
const profileId = generateId()
|
||||
const profileId = uuidv4()
|
||||
const now = new Date()
|
||||
|
||||
const details: CreatorProfileDetails = {}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { hasCredentialSetsAccess } from '@/lib/billing'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { sendEmail } from '@/lib/messaging/email/mailer'
|
||||
|
||||
const logger = createLogger('CredentialSetInvite')
|
||||
@@ -106,12 +105,12 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
const body = await req.json()
|
||||
const { email } = createInviteSchema.parse(body)
|
||||
|
||||
const token = generateId()
|
||||
const token = crypto.randomUUID()
|
||||
const expiresAt = new Date()
|
||||
expiresAt.setDate(expiresAt.getDate() + 7)
|
||||
|
||||
const invitation = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
credentialSetId: id,
|
||||
email: email || null,
|
||||
token,
|
||||
|
||||
@@ -6,7 +6,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { hasCredentialSetsAccess } from '@/lib/billing'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { syncAllWebhooksForCredentialSet } from '@/lib/webhooks/utils.server'
|
||||
|
||||
const logger = createLogger('CredentialSetMembers')
|
||||
@@ -168,7 +167,7 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i
|
||||
return NextResponse.json({ error: 'Member not found' }, { status: 404 })
|
||||
}
|
||||
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
|
||||
// Use transaction to ensure member deletion + webhook sync are atomic
|
||||
await db.transaction(async (tx) => {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { syncAllWebhooksForCredentialSet } from '@/lib/webhooks/utils.server'
|
||||
|
||||
const logger = createLogger('CredentialSetInviteToken')
|
||||
@@ -126,11 +125,11 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ tok
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
|
||||
await db.transaction(async (tx) => {
|
||||
await tx.insert(credentialSetMember).values({
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
credentialSetId: invitation.credentialSetId,
|
||||
userId: session.user.id,
|
||||
status: 'active',
|
||||
|
||||
@@ -5,7 +5,6 @@ import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { syncAllWebhooksForCredentialSet } from '@/lib/webhooks/utils.server'
|
||||
|
||||
const logger = createLogger('CredentialSetMemberships')
|
||||
@@ -61,7 +60,7 @@ export async function DELETE(req: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
|
||||
// Use transaction to ensure revocation + webhook sync are atomic
|
||||
await db.transaction(async (tx) => {
|
||||
|
||||
@@ -7,7 +7,6 @@ import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { hasCredentialSetsAccess } from '@/lib/billing'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
const logger = createLogger('CredentialSets')
|
||||
|
||||
@@ -151,7 +150,7 @@ export async function POST(req: Request) {
|
||||
|
||||
const now = new Date()
|
||||
const newCredentialSet = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
organizationId,
|
||||
name,
|
||||
description: description || null,
|
||||
|
||||
@@ -5,7 +5,6 @@ import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
|
||||
|
||||
const logger = createLogger('CredentialMembersAPI')
|
||||
@@ -134,7 +133,7 @@ export async function POST(request: NextRequest, context: RouteContext) {
|
||||
}
|
||||
|
||||
await db.insert(credentialMember).values({
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
credentialId,
|
||||
userId,
|
||||
role,
|
||||
|
||||
@@ -6,7 +6,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { encryptSecret } from '@/lib/core/security/encryption'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { getCredentialActorContext } from '@/lib/credentials/access'
|
||||
import {
|
||||
syncPersonalEnvCredentialsForUser,
|
||||
@@ -274,7 +273,7 @@ export async function DELETE(
|
||||
await db
|
||||
.insert(workspaceEnvironment)
|
||||
.values({
|
||||
id: workspaceRow?.id || generateId(),
|
||||
id: workspaceRow?.id || crypto.randomUUID(),
|
||||
workspaceId: access.credential.workspaceId,
|
||||
variables: current,
|
||||
createdAt: workspaceRow?.createdAt || new Date(),
|
||||
|
||||
@@ -5,7 +5,6 @@ import { and, eq, lt } from 'drizzle-orm'
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
|
||||
|
||||
const logger = createLogger('CredentialDraftAPI')
|
||||
@@ -76,7 +75,7 @@ export async function POST(request: Request) {
|
||||
await db
|
||||
.insert(pendingCredentialDraft)
|
||||
.values({
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
userId,
|
||||
workspaceId,
|
||||
providerId,
|
||||
|
||||
@@ -7,7 +7,6 @@ import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { encryptSecret } from '@/lib/core/security/encryption'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { getWorkspaceMemberUserIds } from '@/lib/credentials/environment'
|
||||
import { syncWorkspaceOAuthCredentialsForUser } from '@/lib/credentials/oauth'
|
||||
import { getServiceConfigByProviderId } from '@/lib/oauth'
|
||||
@@ -537,7 +536,7 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
const credentialId = generateId()
|
||||
const credentialId = crypto.randomUUID()
|
||||
const [workspaceRow] = await db
|
||||
.select({ ownerId: workspace.ownerId })
|
||||
.from(workspace)
|
||||
@@ -566,7 +565,7 @@ export async function POST(request: NextRequest) {
|
||||
if (workspaceUserIds.length > 0) {
|
||||
for (const memberUserId of workspaceUserIds) {
|
||||
await tx.insert(credentialMember).values({
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
credentialId,
|
||||
userId: memberUserId,
|
||||
role:
|
||||
@@ -583,7 +582,7 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
} else {
|
||||
await tx.insert(credentialMember).values({
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
credentialId,
|
||||
userId: session.user.id,
|
||||
role: 'admin',
|
||||
|
||||
@@ -8,7 +8,6 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { decryptSecret, encryptSecret } from '@/lib/core/security/encryption'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { syncPersonalEnvCredentialsForUser } from '@/lib/credentials/environment'
|
||||
import type { EnvironmentVariable } from '@/stores/settings/environment'
|
||||
|
||||
@@ -43,7 +42,7 @@ export async function POST(req: NextRequest) {
|
||||
await db
|
||||
.insert(environment)
|
||||
.values({
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
userId: session.user.id,
|
||||
variables: encryptedVariables,
|
||||
updatedAt: new Date(),
|
||||
|
||||
@@ -82,12 +82,8 @@ vi.mock('drizzle-orm', () => ({
|
||||
sql: vi.fn((strings: unknown, ...values: unknown[]) => ({ type: 'sql', sql: strings, values })),
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/core/utils/uuid', () => ({
|
||||
generateId: vi.fn(() => 'test-uuid'),
|
||||
generateShortId: vi.fn(() => 'mock-short-id'),
|
||||
isValidUuid: vi.fn((v: string) =>
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v)
|
||||
),
|
||||
vi.mock('uuid', () => ({
|
||||
v4: vi.fn().mockReturnValue('test-uuid'),
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/auth', () => ({
|
||||
|
||||
@@ -91,12 +91,8 @@ vi.mock('drizzle-orm', () => ({
|
||||
sql: vi.fn((strings: unknown, ...values: unknown[]) => ({ type: 'sql', sql: strings, values })),
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/core/utils/uuid', () => ({
|
||||
generateId: vi.fn(() => 'test-uuid'),
|
||||
generateShortId: vi.fn(() => 'mock-short-id'),
|
||||
isValidUuid: vi.fn((v: string) =>
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v)
|
||||
),
|
||||
vi.mock('uuid', () => ({
|
||||
v4: vi.fn().mockReturnValue('test-uuid'),
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/auth', () => ({
|
||||
@@ -462,10 +458,10 @@ describe('File Upload Security Tests', () => {
|
||||
expect(response.status).toBe(200)
|
||||
})
|
||||
|
||||
it('should reject unsupported file types', async () => {
|
||||
it('should reject JavaScript files', async () => {
|
||||
const formData = new FormData()
|
||||
const content = 'binary data'
|
||||
const file = new File([content], 'archive.exe', { type: 'application/octet-stream' })
|
||||
const maliciousJs = 'alert("XSS")'
|
||||
const file = new File([maliciousJs], 'malicious.js', { type: 'application/javascript' })
|
||||
formData.append('file', file)
|
||||
formData.append('context', 'workspace')
|
||||
formData.append('workspaceId', 'test-workspace-id')
|
||||
@@ -479,7 +475,7 @@ describe('File Upload Security Tests', () => {
|
||||
|
||||
expect(response.status).toBe(400)
|
||||
const data = await response.json()
|
||||
expect(data.message).toContain("File type 'exe' is not allowed")
|
||||
expect(data.message).toContain("File type 'js' is not allowed")
|
||||
})
|
||||
|
||||
it('should reject files without extensions', async () => {
|
||||
|
||||
@@ -8,7 +8,6 @@ import { generateWorkspaceFileKey } from '@/lib/uploads/contexts/workspace/works
|
||||
import { isImageFileType } from '@/lib/uploads/utils/file-utils'
|
||||
import {
|
||||
SUPPORTED_AUDIO_EXTENSIONS,
|
||||
SUPPORTED_CODE_EXTENSIONS,
|
||||
SUPPORTED_DOCUMENT_EXTENSIONS,
|
||||
SUPPORTED_VIDEO_EXTENSIONS,
|
||||
validateFileType,
|
||||
@@ -24,7 +23,6 @@ const IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'] as const
|
||||
|
||||
const ALLOWED_EXTENSIONS = new Set<string>([
|
||||
...SUPPORTED_DOCUMENT_EXTENSIONS,
|
||||
...SUPPORTED_CODE_EXTENSIONS,
|
||||
...IMAGE_EXTENSIONS,
|
||||
...SUPPORTED_AUDIO_EXTENSIONS,
|
||||
...SUPPORTED_VIDEO_EXTENSIONS,
|
||||
|
||||
@@ -7,7 +7,6 @@ import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { duplicateWorkflow } from '@/lib/workflows/persistence/duplicate'
|
||||
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
|
||||
|
||||
@@ -68,7 +67,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
const targetWorkspaceId = workspaceId || sourceFolder.workspaceId
|
||||
|
||||
const { newFolderId, folderMapping } = await db.transaction(async (tx) => {
|
||||
const newFolderId = clientNewId || generateId()
|
||||
const newFolderId = clientNewId || crypto.randomUUID()
|
||||
const now = new Date()
|
||||
const targetParentId = parentId ?? sourceFolder.parentId
|
||||
|
||||
@@ -228,7 +227,7 @@ async function duplicateFolderStructure(
|
||||
)
|
||||
|
||||
for (const childFolder of childFolders) {
|
||||
const newChildFolderId = generateId()
|
||||
const newChildFolderId = crypto.randomUUID()
|
||||
folderMapping.set(childFolder.id, newChildFolderId)
|
||||
|
||||
await tx.insert(workflowFolder).values({
|
||||
|
||||
@@ -6,7 +6,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { captureServerEvent } from '@/lib/posthog/server'
|
||||
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
|
||||
|
||||
@@ -93,7 +92,7 @@ export async function POST(request: NextRequest) {
|
||||
)
|
||||
}
|
||||
|
||||
const id = clientId || generateId()
|
||||
const id = clientId || crypto.randomUUID()
|
||||
|
||||
const newFolder = await db.transaction(async (tx) => {
|
||||
let sortOrder: number
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { form, workflow, workflowBlocks } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -6,7 +7,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { addCorsHeaders, validateAuthToken } from '@/lib/core/security/deployment'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { preprocessExecution } from '@/lib/execution/preprocessing'
|
||||
import { LoggingSession } from '@/lib/logs/execution/logging-session'
|
||||
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
|
||||
@@ -119,7 +119,7 @@ export async function POST(
|
||||
)
|
||||
}
|
||||
|
||||
const executionId = generateId()
|
||||
const executionId = randomUUID()
|
||||
const loggingSession = new LoggingSession(
|
||||
deployment.workflowId,
|
||||
executionId,
|
||||
@@ -165,7 +165,7 @@ export async function POST(
|
||||
return addCorsHeaders(createErrorResponse('No form data provided', 400), request)
|
||||
}
|
||||
|
||||
const executionId = generateId()
|
||||
const executionId = randomUUID()
|
||||
const loggingSession = new LoggingSession(deployment.workflowId, executionId, 'form', requestId)
|
||||
|
||||
const preprocessResult = await preprocessExecution({
|
||||
|
||||
@@ -3,13 +3,13 @@ import { form } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { isDev } from '@/lib/core/config/feature-flags'
|
||||
import { encryptSecret } from '@/lib/core/security/encryption'
|
||||
import { getEmailDomain } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { deployWorkflow } from '@/lib/workflows/persistence/utils'
|
||||
import {
|
||||
checkWorkflowAccessForFormCreation,
|
||||
@@ -158,7 +158,7 @@ export async function POST(request: NextRequest) {
|
||||
encryptedPassword = encrypted
|
||||
}
|
||||
|
||||
const id = generateId()
|
||||
const id = uuidv4()
|
||||
|
||||
logger.info('Creating form deployment with values:', {
|
||||
workflowId,
|
||||
|
||||
@@ -9,7 +9,6 @@ import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { hasLiveSyncAccess } from '@/lib/billing/core/subscription'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { dispatchSync } from '@/lib/knowledge/connectors/sync-engine'
|
||||
import { allocateTagSlots } from '@/lib/knowledge/constants'
|
||||
import { createTagDefinition } from '@/lib/knowledge/tags/service'
|
||||
@@ -212,7 +211,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
const connectorId = generateId()
|
||||
const connectorId = crypto.randomUUID()
|
||||
const nextSyncAt =
|
||||
syncIntervalMinutes > 0 ? new Date(now.getTime() + syncIntervalMinutes * 60 * 1000) : null
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { deleteChunk, updateChunk } from '@/lib/knowledge/chunks/service'
|
||||
import { checkChunkAccess } from '@/app/api/knowledge/utils'
|
||||
|
||||
@@ -17,7 +17,7 @@ export async function GET(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string; documentId: string; chunkId: string }> }
|
||||
) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId, documentId, chunkId } = await params
|
||||
|
||||
try {
|
||||
@@ -65,7 +65,7 @@ export async function PUT(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string; documentId: string; chunkId: string }> }
|
||||
) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId, documentId, chunkId } = await params
|
||||
|
||||
try {
|
||||
@@ -147,7 +147,7 @@ export async function DELETE(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string; documentId: string; chunkId: string }> }
|
||||
) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId, documentId, chunkId } = await params
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { SUPPORTED_FIELD_TYPES } from '@/lib/knowledge/constants'
|
||||
import {
|
||||
cleanupUnusedTagDefinitions,
|
||||
@@ -34,7 +34,7 @@ export async function GET(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string; documentId: string }> }
|
||||
) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId, documentId } = await params
|
||||
|
||||
try {
|
||||
@@ -79,7 +79,7 @@ export async function POST(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string; documentId: string }> }
|
||||
) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId, documentId } = await params
|
||||
|
||||
try {
|
||||
@@ -160,7 +160,7 @@ export async function DELETE(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string; documentId: string }> }
|
||||
) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId, documentId } = await params
|
||||
const { searchParams } = new URL(req.url)
|
||||
const action = searchParams.get('action') // 'cleanup' or 'all'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
bulkDocumentOperation,
|
||||
bulkDocumentOperationByFilter,
|
||||
@@ -66,7 +66,7 @@ const BulkUpdateDocumentsSchema = z
|
||||
})
|
||||
|
||||
export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
|
||||
try {
|
||||
@@ -164,7 +164,7 @@ export async function GET(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
|
||||
try {
|
||||
@@ -398,7 +398,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
}
|
||||
|
||||
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { document } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -6,7 +7,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
createDocumentRecords,
|
||||
deleteDocument,
|
||||
@@ -35,7 +35,7 @@ const UpsertDocumentSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { getNextAvailableSlot, getTagDefinitions } from '@/lib/knowledge/tags/service'
|
||||
import { checkKnowledgeBaseAccess } from '@/app/api/knowledge/utils'
|
||||
|
||||
@@ -9,7 +9,7 @@ const logger = createLogger('NextAvailableSlotAPI')
|
||||
|
||||
// GET /api/knowledge/[id]/next-available-slot - Get the next available tag slot for a knowledge base and field type
|
||||
export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
const { searchParams } = new URL(req.url)
|
||||
const fieldType = searchParams.get('fieldType')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { deleteTagDefinition } from '@/lib/knowledge/tags/service'
|
||||
import { checkKnowledgeBaseWriteAccess } from '@/app/api/knowledge/utils'
|
||||
|
||||
@@ -14,7 +14,7 @@ export async function DELETE(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string; tagId: string }> }
|
||||
) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId, tagId } = await params
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { AuthType, checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { SUPPORTED_FIELD_TYPES } from '@/lib/knowledge/constants'
|
||||
import { createTagDefinition, getTagDefinitions } from '@/lib/knowledge/tags/service'
|
||||
import { checkKnowledgeBaseWriteAccess } from '@/app/api/knowledge/utils'
|
||||
@@ -13,7 +13,7 @@ const logger = createLogger('KnowledgeBaseTagDefinitionsAPI')
|
||||
|
||||
// GET /api/knowledge/[id]/tag-definitions - Get all tag definitions for a knowledge base
|
||||
export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
|
||||
try {
|
||||
@@ -53,7 +53,7 @@ export async function GET(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
|
||||
// POST /api/knowledge/[id]/tag-definitions - Create a new tag definition
|
||||
export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { getTagUsage } from '@/lib/knowledge/tags/service'
|
||||
import { checkKnowledgeBaseAccess } from '@/app/api/knowledge/utils'
|
||||
|
||||
@@ -11,7 +11,7 @@ const logger = createLogger('TagUsageAPI')
|
||||
|
||||
// GET /api/knowledge/[id]/tag-usage - Get usage statistics for all tag definitions
|
||||
export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
const { id: knowledgeBaseId } = await params
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
||||
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
|
||||
import {
|
||||
@@ -29,7 +30,6 @@ import { DIRECT_TOOL_DEFS, SUBAGENT_TOOL_DEFS } from '@/lib/copilot/tools/mcp/de
|
||||
import { env } from '@/lib/core/config/env'
|
||||
import { RateLimiter } from '@/lib/core/rate-limiter'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
authorizeWorkflowByWorkspacePermission,
|
||||
resolveWorkflowIdForUser,
|
||||
@@ -638,7 +638,7 @@ async function handleDirectToolCall(
|
||||
)
|
||||
|
||||
const toolCall = {
|
||||
id: generateId(),
|
||||
id: randomUUID(),
|
||||
name: toolDef.toolId,
|
||||
status: 'pending' as const,
|
||||
params: args as Record<string, any>,
|
||||
@@ -715,7 +715,7 @@ async function handleBuildToolCall(
|
||||
}
|
||||
}
|
||||
|
||||
const chatId = generateId()
|
||||
const chatId = randomUUID()
|
||||
|
||||
const requestPayload = {
|
||||
message: requestText,
|
||||
@@ -724,12 +724,12 @@ async function handleBuildToolCall(
|
||||
model: DEFAULT_COPILOT_MODEL,
|
||||
mode: 'agent',
|
||||
commands: ['fast'],
|
||||
messageId: generateId(),
|
||||
messageId: randomUUID(),
|
||||
chatId,
|
||||
}
|
||||
|
||||
const executionId = generateId()
|
||||
const runId = generateId()
|
||||
const executionId = crypto.randomUUID()
|
||||
const runId = crypto.randomUUID()
|
||||
const messageId = requestPayload.messageId as string
|
||||
|
||||
await createRunSegment({
|
||||
|
||||
@@ -4,7 +4,6 @@ import { createLogger } from '@sim/logger'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
McpDnsResolutionError,
|
||||
McpDomainNotAllowedError,
|
||||
@@ -103,7 +102,7 @@ export const POST = withMcpAuth('write')(
|
||||
throw e
|
||||
}
|
||||
|
||||
const serverId = body.url ? generateMcpServerId(workspaceId, body.url) : generateId()
|
||||
const serverId = body.url ? generateMcpServerId(workspaceId, body.url) : crypto.randomUUID()
|
||||
|
||||
const [existingServer] = await db
|
||||
.select({ id: mcpServers.id, deletedAt: mcpServers.deletedAt })
|
||||
|
||||
@@ -4,7 +4,6 @@ import { createLogger } from '@sim/logger'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware'
|
||||
import { mcpPubSub } from '@/lib/mcp/pubsub'
|
||||
import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils'
|
||||
@@ -194,7 +193,7 @@ export const POST = withMcpAuth<RouteParams>('write')(
|
||||
? body.parameterSchema
|
||||
: await generateParameterSchemaForWorkflow(body.workflowId)
|
||||
|
||||
const toolId = generateId()
|
||||
const toolId = crypto.randomUUID()
|
||||
const [tool] = await db
|
||||
.insert(workflowMcpTool)
|
||||
.values({
|
||||
|
||||
@@ -4,7 +4,6 @@ import { createLogger } from '@sim/logger'
|
||||
import { and, eq, inArray, isNull, sql } from 'drizzle-orm'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { getParsedBody, withMcpAuth } from '@/lib/mcp/middleware'
|
||||
import { mcpPubSub } from '@/lib/mcp/pubsub'
|
||||
import { createMcpErrorResponse, createMcpSuccessResponse } from '@/lib/mcp/utils'
|
||||
@@ -113,7 +112,7 @@ export const POST = withMcpAuth('write')(
|
||||
)
|
||||
}
|
||||
|
||||
const serverId = generateId()
|
||||
const serverId = crypto.randomUUID()
|
||||
|
||||
const [server] = await db
|
||||
.insert(workflowMcpServer)
|
||||
@@ -169,7 +168,7 @@ export const POST = withMcpAuth('write')(
|
||||
|
||||
const parameterSchema = await generateParameterSchemaForWorkflow(workflowRecord.id)
|
||||
|
||||
const toolId = generateId()
|
||||
const toolId = crypto.randomUUID()
|
||||
await db.insert(workflowMcpTool).values({
|
||||
id: toolId,
|
||||
serverId,
|
||||
|
||||
@@ -5,7 +5,6 @@ import { and, eq, isNull, like } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
|
||||
|
||||
const logger = createLogger('MemoryAPI')
|
||||
@@ -164,7 +163,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
const initialData = Array.isArray(data) ? data : [data]
|
||||
const now = new Date()
|
||||
const id = `mem_${generateId().replace(/-/g, '')}`
|
||||
const id = `mem_${crypto.randomUUID().replace(/-/g, '')}`
|
||||
|
||||
const { sql } = await import('drizzle-orm')
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import { processContextsServer, resolveActiveResourceContext } from '@/lib/copil
|
||||
import { createRequestTracker, createUnauthorizedResponse } from '@/lib/copilot/request-helpers'
|
||||
import { taskPubSub } from '@/lib/copilot/task-events'
|
||||
import { generateWorkspaceContext } from '@/lib/copilot/workspace-context'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
assertActiveWorkspaceAccess,
|
||||
getUserEntityPermissions,
|
||||
@@ -110,7 +109,7 @@ export async function POST(req: NextRequest) {
|
||||
userTimezone,
|
||||
} = MothershipMessageSchema.parse(body)
|
||||
|
||||
const userMessageId = providedMessageId || generateId()
|
||||
const userMessageId = providedMessageId || crypto.randomUUID()
|
||||
userMessageIdForLogs = userMessageId
|
||||
const reqLogger = logger.withMetadata({
|
||||
requestId: tracker.requestId,
|
||||
@@ -281,8 +280,8 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
const executionId = generateId()
|
||||
const runId = generateId()
|
||||
const executionId = crypto.randomUUID()
|
||||
const runId = crypto.randomUUID()
|
||||
const stream = createSSEStream({
|
||||
requestPayload,
|
||||
userId: authenticatedUserId,
|
||||
@@ -311,7 +310,7 @@ export async function POST(req: NextRequest) {
|
||||
if (!result.success) return
|
||||
|
||||
const assistantMessage: Record<string, unknown> = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
role: 'assistant' as const,
|
||||
content: result.content,
|
||||
timestamp: new Date().toISOString(),
|
||||
|
||||
@@ -7,7 +7,6 @@ import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { releasePendingChatStream } from '@/lib/copilot/chat-streaming'
|
||||
import { taskPubSub } from '@/lib/copilot/task-events'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
const logger = createLogger('MothershipChatStopAPI')
|
||||
|
||||
@@ -72,7 +71,7 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
if (hasContent || hasBlocks) {
|
||||
const assistantMessage: Record<string, unknown> = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
role: 'assistant' as const,
|
||||
content,
|
||||
timestamp: new Date().toISOString(),
|
||||
|
||||
@@ -6,7 +6,6 @@ import { createRunSegment } from '@/lib/copilot/async-runs/repository'
|
||||
import { buildIntegrationToolSchemas } from '@/lib/copilot/chat-payload'
|
||||
import { orchestrateCopilotStream } from '@/lib/copilot/orchestrator'
|
||||
import { generateWorkspaceContext } from '@/lib/copilot/workspace-context'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
assertActiveWorkspaceAccess,
|
||||
getUserEntityPermissions,
|
||||
@@ -51,8 +50,8 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
await assertActiveWorkspaceAccess(workspaceId, userId)
|
||||
|
||||
const effectiveChatId = chatId || generateId()
|
||||
messageId = generateId()
|
||||
const effectiveChatId = chatId || crypto.randomUUID()
|
||||
messageId = crypto.randomUUID()
|
||||
const reqLogger = logger.withMetadata({ messageId })
|
||||
const [workspaceContext, integrationTools, userPermission] = await Promise.all([
|
||||
generateWorkspaceContext(workspaceId, userId),
|
||||
@@ -73,8 +72,8 @@ export async function POST(req: NextRequest) {
|
||||
...(userPermission ? { userPermission } : {}),
|
||||
}
|
||||
|
||||
const executionId = generateId()
|
||||
const runId = generateId()
|
||||
const executionId = crypto.randomUUID()
|
||||
const runId = crypto.randomUUID()
|
||||
|
||||
await createRunSegment({
|
||||
id: runId,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { verifyCronAuth } from '@/lib/auth/internal'
|
||||
import { acquireLock, releaseLock } from '@/lib/core/config/redis'
|
||||
import { generateShortId } from '@/lib/core/utils/uuid'
|
||||
import { pollInactivityAlerts } from '@/lib/notifications/inactivity-polling'
|
||||
|
||||
const logger = createLogger('InactivityAlertPoll')
|
||||
@@ -13,7 +13,7 @@ const LOCK_KEY = 'inactivity-alert-polling-lock'
|
||||
const LOCK_TTL_SECONDS = 120
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const requestId = generateShortId()
|
||||
const requestId = nanoid()
|
||||
logger.info(`Inactivity alert polling triggered (${requestId})`)
|
||||
|
||||
let lockAcquired = false
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import {
|
||||
invitation,
|
||||
@@ -26,7 +27,6 @@ import { isOrgPlan, sqlIsPro } from '@/lib/billing/plan-helpers'
|
||||
import { requireStripeClient } from '@/lib/billing/stripe-client'
|
||||
import { ENTITLED_SUBSCRIPTION_STATUSES } from '@/lib/billing/subscriptions/utils'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { syncWorkspaceEnvCredentials } from '@/lib/credentials/environment'
|
||||
import { sendEmail } from '@/lib/messaging/email/mailer'
|
||||
|
||||
@@ -321,7 +321,7 @@ export async function PUT(
|
||||
|
||||
if (status === 'accepted') {
|
||||
await tx.insert(member).values({
|
||||
id: generateId(),
|
||||
id: randomUUID(),
|
||||
userId: session.user.id,
|
||||
organizationId,
|
||||
role: orgInvitation.role,
|
||||
@@ -423,7 +423,7 @@ export async function PUT(
|
||||
|
||||
if (autoAddGroup) {
|
||||
await tx.insert(permissionGroupMember).values({
|
||||
id: generateId(),
|
||||
id: randomUUID(),
|
||||
permissionGroupId: autoAddGroup.id,
|
||||
userId: session.user.id,
|
||||
assignedBy: null,
|
||||
@@ -497,7 +497,7 @@ export async function PUT(
|
||||
}
|
||||
} else {
|
||||
await tx.insert(permissions).values({
|
||||
id: generateId(),
|
||||
id: randomUUID(),
|
||||
entityType: 'workspace',
|
||||
entityId: wsInvitation.workspaceId,
|
||||
userId: session.user.id,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import {
|
||||
invitation,
|
||||
@@ -23,7 +24,6 @@ import {
|
||||
validateSeatAvailability,
|
||||
} from '@/lib/billing/validation/seat-management'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { sendEmail } from '@/lib/messaging/email/mailer'
|
||||
import { quickValidateEmail } from '@/lib/messaging/email/validation'
|
||||
import { hasWorkspaceAdminAccess } from '@/lib/workspaces/permissions/utils'
|
||||
@@ -293,7 +293,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
|
||||
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days
|
||||
const invitationsToCreate = emailsToInvite.map((email: string) => ({
|
||||
id: generateId(),
|
||||
id: randomUUID(),
|
||||
email,
|
||||
inviterId: session.user.id,
|
||||
organizationId,
|
||||
@@ -310,8 +310,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
for (const email of emailsToInvite) {
|
||||
const orgInviteForEmail = invitationsToCreate.find((inv) => inv.email === email)
|
||||
for (const wsInvitation of validWorkspaceInvitations) {
|
||||
const wsInvitationId = generateId()
|
||||
const token = generateId()
|
||||
const wsInvitationId = randomUUID()
|
||||
const token = randomUUID()
|
||||
|
||||
await db.insert(workspaceInvitation).values({
|
||||
id: wsInvitationId,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { invitation, member, organization, user, userStats } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -9,7 +10,6 @@ import { getSession } from '@/lib/auth'
|
||||
import { getUserUsageData } from '@/lib/billing/core/usage'
|
||||
import { validateSeatAvailability } from '@/lib/billing/validation/seat-management'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { sendEmail } from '@/lib/messaging/email/mailer'
|
||||
import { quickValidateEmail } from '@/lib/messaging/email/validation'
|
||||
|
||||
@@ -231,7 +231,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
}
|
||||
|
||||
// Create invitation
|
||||
const invitationId = generateId()
|
||||
const invitationId = randomUUID()
|
||||
const expiresAt = new Date()
|
||||
expiresAt.setDate(expiresAt.getDate() + 7) // 7 days expiry
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { hasAccessControlAccess } from '@/lib/billing'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
const logger = createLogger('PermissionGroupBulkMembers')
|
||||
|
||||
@@ -130,7 +129,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
}
|
||||
|
||||
const newMembers = usersToAdd.map((userId) => ({
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
permissionGroupId: id,
|
||||
userId,
|
||||
assignedBy: session.user.id,
|
||||
|
||||
@@ -7,7 +7,6 @@ import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { hasAccessControlAccess } from '@/lib/billing'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
const logger = createLogger('PermissionGroupMembers')
|
||||
|
||||
@@ -138,7 +137,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
||||
}
|
||||
|
||||
const memberData = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
permissionGroupId: id,
|
||||
userId,
|
||||
assignedBy: session.user.id,
|
||||
|
||||
@@ -7,7 +7,6 @@ import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { hasAccessControlAccess } from '@/lib/billing'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
DEFAULT_PERMISSION_GROUP_CONFIG,
|
||||
type PermissionGroupConfig,
|
||||
@@ -182,7 +181,7 @@ export async function POST(req: Request) {
|
||||
|
||||
const now = new Date()
|
||||
const newGroup = {
|
||||
id: generateId(),
|
||||
id: crypto.randomUUID(),
|
||||
organizationId,
|
||||
name,
|
||||
description: description || null,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { AuthType } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { preprocessExecution } from '@/lib/execution/preprocessing'
|
||||
import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-manager'
|
||||
import { getWorkspaceBilledAccountUserId } from '@/lib/workspaces/utils'
|
||||
@@ -60,7 +60,7 @@ export async function POST(
|
||||
userId = billedAccountUserId
|
||||
}
|
||||
|
||||
const resumeExecutionId = generateId()
|
||||
const resumeExecutionId = randomUUID()
|
||||
const requestId = generateRequestId()
|
||||
|
||||
logger.info(`[${requestId}] Preprocessing resume execution`, {
|
||||
|
||||
@@ -132,12 +132,8 @@ vi.mock('@sim/db', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/core/utils/uuid', () => ({
|
||||
generateId: vi.fn(() => 'schedule-execution-1'),
|
||||
generateShortId: vi.fn(() => 'mock-short-id'),
|
||||
isValidUuid: vi.fn((v: string) =>
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v)
|
||||
),
|
||||
vi.mock('uuid', () => ({
|
||||
v4: vi.fn().mockReturnValue('schedule-execution-1'),
|
||||
}))
|
||||
|
||||
import { GET } from './route'
|
||||
|
||||
@@ -2,11 +2,11 @@ import { db, workflowDeploymentVersion, workflowSchedule } from '@sim/db'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq, isNull, lt, lte, ne, not, or, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { verifyCronAuth } from '@/lib/auth/internal'
|
||||
import { getJobQueue, shouldExecuteInline } from '@/lib/core/async-jobs'
|
||||
import { createBullMQJobData, isBullMQEnabled } from '@/lib/core/bullmq'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { enqueueWorkspaceDispatch } from '@/lib/core/workspace-dispatch'
|
||||
import {
|
||||
executeJobInline,
|
||||
@@ -89,7 +89,7 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
const schedulePromises = dueSchedules.map(async (schedule) => {
|
||||
const queueTime = schedule.lastQueuedAt ?? queuedAt
|
||||
const executionId = generateId()
|
||||
const executionId = uuidv4()
|
||||
const correlation = {
|
||||
executionId,
|
||||
requestId,
|
||||
|
||||
@@ -5,7 +5,6 @@ import { and, eq, isNull, or } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { captureServerEvent } from '@/lib/posthog/server'
|
||||
import { validateCronExpression } from '@/lib/workflows/schedules/utils'
|
||||
import { authorizeWorkflowByWorkspacePermission } from '@/lib/workflows/utils'
|
||||
@@ -250,7 +249,7 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
const id = generateId()
|
||||
const id = crypto.randomUUID()
|
||||
|
||||
await db.insert(workflowSchedule).values({
|
||||
id,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { createLogger } from '@sim/logger'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { verifyEffectiveSuperUser } from '@/lib/templates/permissions'
|
||||
import { parseWorkflowJson } from '@/lib/workflows/operations/import-export'
|
||||
import {
|
||||
@@ -119,7 +118,7 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Create new workflow record
|
||||
const newWorkflowId = generateId()
|
||||
const newWorkflowId = crypto.randomUUID()
|
||||
const now = new Date()
|
||||
const dedupedName = await deduplicateWorkflowName(
|
||||
`[Debug Import] ${sourceWorkflow.name}`,
|
||||
|
||||
@@ -2,7 +2,6 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
batchInsertRows,
|
||||
createTable,
|
||||
@@ -226,7 +225,7 @@ export async function POST(request: NextRequest) {
|
||||
let inserted = 0
|
||||
for (let i = 0; i < coerced.length; i += MAX_BATCH_SIZE) {
|
||||
const batch = coerced.slice(i, i + MAX_BATCH_SIZE)
|
||||
const batchRequestId = generateId().slice(0, 8)
|
||||
const batchRequestId = crypto.randomUUID().slice(0, 8)
|
||||
const result = await batchInsertRows(
|
||||
{ tableId: table.id, rows: batch, workspaceId, userId: authResult.userId },
|
||||
table,
|
||||
|
||||
@@ -3,9 +3,9 @@ import { templateStars, templates } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
const logger = createLogger('TemplateStarAPI')
|
||||
|
||||
@@ -86,7 +86,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
await db.transaction(async (tx) => {
|
||||
// Add the star record
|
||||
await tx.insert(templateStars).values({
|
||||
id: generateId(),
|
||||
id: uuidv4(),
|
||||
userId: session.user.id,
|
||||
templateId: id,
|
||||
starredAt: new Date(),
|
||||
|
||||
@@ -3,10 +3,10 @@ import { templates, workflow, workflowDeploymentVersion } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { getInternalApiBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { canAccessTemplate, verifyTemplateOwnership } from '@/lib/templates/permissions'
|
||||
import {
|
||||
type RegenerateStateInput,
|
||||
@@ -93,7 +93,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
const templateData = template[0]
|
||||
|
||||
// Create a new workflow ID
|
||||
const newWorkflowId = generateId()
|
||||
const newWorkflowId = uuidv4()
|
||||
const now = new Date()
|
||||
|
||||
// Extract variables from the template state and remap to the new workflow
|
||||
@@ -104,7 +104,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
if (!templateVariables || typeof templateVariables !== 'object') return {}
|
||||
const mapped: Record<string, any> = {}
|
||||
for (const [, variable] of Object.entries(templateVariables)) {
|
||||
const newVarId = generateId()
|
||||
const newVarId = uuidv4()
|
||||
mapped[newVarId] = { ...variable, id: newVarId, workflowId: newWorkflowId }
|
||||
}
|
||||
return mapped
|
||||
@@ -178,7 +178,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
|
||||
|
||||
// Create a deployment version for the new workflow
|
||||
if (templateData.state) {
|
||||
const newDeploymentVersionId = generateId()
|
||||
const newDeploymentVersionId = uuidv4()
|
||||
await tx.insert(workflowDeploymentVersion).values({
|
||||
id: newDeploymentVersionId,
|
||||
workflowId: newWorkflowId,
|
||||
|
||||
@@ -9,11 +9,11 @@ import {
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, desc, eq, ilike, or, sql } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { z } from 'zod'
|
||||
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { canAccessTemplate, verifyEffectiveSuperUser } from '@/lib/templates/permissions'
|
||||
import {
|
||||
extractRequiredCredentials,
|
||||
@@ -267,7 +267,7 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: permissionError || 'Access denied' }, { status: 403 })
|
||||
}
|
||||
|
||||
const templateId = generateId()
|
||||
const templateId = uuidv4()
|
||||
const now = new Date()
|
||||
|
||||
// Get the active deployment version for the workflow to copy its state
|
||||
|
||||
@@ -6,7 +6,6 @@ import { createA2AClient, extractTextContent, isTerminalState } from '@/lib/a2a/
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { validateUrlWithDNS } from '@/lib/core/security/input-validation.server'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
@@ -143,7 +142,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
const message: Message = {
|
||||
kind: 'message',
|
||||
messageId: generateId(),
|
||||
messageId: crypto.randomUUID(),
|
||||
role: 'user',
|
||||
parts,
|
||||
...(validatedData.taskId && { taskId: validatedData.taskId }),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createRawDynamoDBClient, describeTable, listTables } from '@/app/api/tools/dynamodb/utils'
|
||||
|
||||
const logger = createLogger('DynamoDBIntrospectAPI')
|
||||
@@ -15,7 +15,7 @@ const IntrospectSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMongoDBConnection, sanitizeCollectionName, validateFilter } from '../utils'
|
||||
|
||||
const logger = createLogger('MongoDBDeleteAPI')
|
||||
@@ -38,7 +38,7 @@ const DeleteSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let client = null
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMongoDBConnection, sanitizeCollectionName, validatePipeline } from '../utils'
|
||||
|
||||
const logger = createLogger('MongoDBExecuteAPI')
|
||||
@@ -30,7 +30,7 @@ const ExecuteSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let client = null
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMongoDBConnection, sanitizeCollectionName } from '../utils'
|
||||
|
||||
const logger = createLogger('MongoDBInsertAPI')
|
||||
@@ -35,7 +35,7 @@ const InsertSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let client = null
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMongoDBConnection, executeIntrospect } from '../utils'
|
||||
|
||||
const logger = createLogger('MongoDBIntrospectAPI')
|
||||
@@ -18,7 +18,7 @@ const IntrospectSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let client = null
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMongoDBConnection, sanitizeCollectionName, validateFilter } from '../utils'
|
||||
|
||||
const logger = createLogger('MongoDBQueryAPI')
|
||||
@@ -47,7 +47,7 @@ const QuerySchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let client = null
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMongoDBConnection, sanitizeCollectionName, validateFilter } from '../utils'
|
||||
|
||||
const logger = createLogger('MongoDBUpdateAPI')
|
||||
@@ -57,7 +57,7 @@ const UpdateSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let client = null
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { buildDeleteQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
||||
|
||||
const logger = createLogger('MySQLDeleteAPI')
|
||||
@@ -19,7 +19,7 @@ const DeleteSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
|
||||
|
||||
const logger = createLogger('MySQLExecuteAPI')
|
||||
@@ -18,7 +18,7 @@ const ExecuteSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { buildInsertQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
||||
|
||||
const logger = createLogger('MySQLInsertAPI')
|
||||
@@ -40,7 +40,7 @@ const InsertSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMySQLConnection, executeIntrospect } from '@/app/api/tools/mysql/utils'
|
||||
|
||||
const logger = createLogger('MySQLIntrospectAPI')
|
||||
@@ -17,7 +17,7 @@ const IntrospectSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
|
||||
|
||||
const logger = createLogger('MySQLQueryAPI')
|
||||
@@ -18,7 +18,7 @@ const QuerySchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { buildUpdateQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
||||
|
||||
const logger = createLogger('MySQLUpdateAPI')
|
||||
@@ -38,7 +38,7 @@ const UpdateSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkInternalAuth(request)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
convertNeo4jTypesToJSON,
|
||||
createNeo4jDriver,
|
||||
@@ -23,7 +23,7 @@ const CreateSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let driver = null
|
||||
let session = null
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createNeo4jDriver, validateCypherQuery } from '@/app/api/tools/neo4j/utils'
|
||||
|
||||
const logger = createLogger('Neo4jDeleteAPI')
|
||||
@@ -20,7 +20,7 @@ const DeleteSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let driver = null
|
||||
let session = null
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
convertNeo4jTypesToJSON,
|
||||
createNeo4jDriver,
|
||||
@@ -23,7 +23,7 @@ const ExecuteSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let driver = null
|
||||
let session = null
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { createNeo4jDriver } from '@/app/api/tools/neo4j/utils'
|
||||
import type { Neo4jNodeSchema, Neo4jRelationshipSchema } from '@/tools/neo4j/types'
|
||||
|
||||
@@ -18,7 +18,7 @@ const IntrospectSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let driver = null
|
||||
let session = null
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
convertNeo4jTypesToJSON,
|
||||
createNeo4jDriver,
|
||||
@@ -23,7 +23,7 @@ const MergeSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let driver = null
|
||||
let session = null
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
convertNeo4jTypesToJSON,
|
||||
createNeo4jDriver,
|
||||
@@ -23,7 +23,7 @@ const QuerySchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let driver = null
|
||||
let session = null
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
convertNeo4jTypesToJSON,
|
||||
createNeo4jDriver,
|
||||
@@ -23,7 +23,7 @@ const UpdateSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
let driver = null
|
||||
let session = null
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -5,7 +6,6 @@ import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { refreshAccessTokenIfNeeded, resolveOAuthAccountId } from '@/app/api/auth/oauth/utils'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -18,7 +18,7 @@ import type { MicrosoftGraphDriveItem } from '@/tools/onedrive/types'
|
||||
* Get files (not folders) from Microsoft OneDrive
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
logger.info(`[${requestId}] OneDrive files request received`)
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -5,7 +6,6 @@ import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { refreshAccessTokenIfNeeded, resolveOAuthAccountId } from '@/app/api/auth/oauth/utils'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -13,7 +13,7 @@ export const dynamic = 'force-dynamic'
|
||||
const logger = createLogger('OneDriveFolderAPI')
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const session = await getSession()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { db } from '@sim/db'
|
||||
import { account } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -5,7 +6,6 @@ import { eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { refreshAccessTokenIfNeeded, resolveOAuthAccountId } from '@/app/api/auth/oauth/utils'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -18,7 +18,7 @@ import type { MicrosoftGraphDriveItem } from '@/tools/onedrive/types'
|
||||
* Get folders from Microsoft OneDrive
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const session = await getSession()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import type { ItemCreateParams } from '@1password/sdk'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
@@ -28,7 +28,7 @@ const CreateItemSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
@@ -55,7 +55,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
const parsedFields = params.fields
|
||||
? (JSON.parse(params.fields) as Array<Record<string, any>>).map((f) => ({
|
||||
id: f.id || generateId().slice(0, 8),
|
||||
id: f.id || randomUUID().slice(0, 8),
|
||||
title: f.label || f.title || '',
|
||||
fieldType: toSdkFieldType(f.type || 'STRING'),
|
||||
value: f.value || '',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import { connectRequest, createOnePasswordClient, resolveCredentials } from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordDeleteItemAPI')
|
||||
@@ -17,7 +17,7 @@ const DeleteItemSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
@@ -22,7 +22,7 @@ const GetItemSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateId } from '@/lib/core/utils/uuid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
@@ -21,7 +21,7 @@ const GetVaultSchema = z.object({
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = generateId().slice(0, 8)
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user