Nicholai b20db98051
Some checks failed
CI / build-and-test (pull_request) Failing after 1m19s
feat(ci,flags,ops): ship end-to-end CI, feature-flag framework, gated surfaces, and ops docs
CI (.gitea/workflows/ci.yaml): lint → typecheck → vitest w/ coverage → OpenNext build → preview smoke → bundle-size budgets; Node 20; npm ci; artifacts; safe env; D1 dry-run scaffold.

Budgets: add scripts/budgets.mjs; TOTAL_STATIC_MAX_BYTES and MAX_ASSET_BYTES thresholds; report top offenders; fail on breach; README CI section.

Flags: add lib/flags.ts with typed booleans and safe defaults (ADMIN_ENABLED, ARTISTS_MODULE_ENABLED, UPLOADS_ADMIN_ENABLED, BOOKING_ENABLED, PUBLIC_APPOINTMENT_REQUESTS_ENABLED, REFERENCE_UPLOADS_PUBLIC_ENABLED, DEPOSITS_ENABLED, PUBLIC_DB_ARTISTS_ENABLED, ADVANCED_NAV_SCROLL_ANIMATIONS_ENABLED, STRICT_CI_GATES_ENABLED, ISR_CACHE_R2_ENABLED); robust parsing; client provider; unit tests.

Wiring: gate Admin shell and admin write APIs (503 JSON on uploads and artists writes); disable booking submit and short-circuit booking mutations when off; render static Hero/Artists when advanced animations off; tests for UI and API guards.

Ops: expand docs/prd/rollback-strategy.md with “Feature Flags Operations,” Cloudflare Dashboard and wrangler.toml steps, preview simulation, incident playbook, and post-toggle smoke checklist.

Release: add docs/releases/2025-09-19-feature-flags-rollout.md with last-good commit, preview/production flag matrices, rollback notes, and smoke results; link from rollback doc.

Chore: fix TS issues (gift-cards boolean handling, Lenis options, tailwind darkMode), remove next-on-pages peer conflict, update package.json scripts, configure Gitea act_runner label, open draft PR to trigger CI.

Refs: CI-1, FF-1, FF-2, FF-3, OPS-1
Impact: defaults preserve current behavior; no runtime changes unless flags flipped
2025-09-19 21:33:09 -06:00

63 lines
2.0 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { getDB } from '@/lib/db'
import { z } from 'zod'
import { Flags } from '@/lib/flags'
export const dynamic = "force-dynamic";
const createFolderSchema = z.object({
name: z.string().min(1, 'Folder name is required'),
path: z.string().default('/'),
})
export async function POST(request: NextRequest, { params }: { params?: any } = {}, context?: any) {
try {
if (!Flags.UPLOADS_ADMIN_ENABLED) {
return NextResponse.json({ error: 'Admin uploads disabled' }, { status: 503 })
}
const session = await getServerSession(authOptions)
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const body = await request.json()
const { name, path } = createFolderSchema.parse(body)
// For this simplified implementation, we'll just return success
// In a real implementation, you would create folder structures in your storage system
// and possibly track them in a separate folders table
const folderId = `folder_${Date.now()}_${Math.random().toString(36).substring(2)}`
const folderPath = path === '/' ? `/${name}` : `${path}/${name}`
// TODO: In a real implementation, you might:
// 1. Create the folder structure in R2 (by creating a placeholder object)
// 2. Store folder metadata in a folders table
// 3. Update file paths to include folder structure
return NextResponse.json({
success: true,
id: folderId,
name,
path: folderPath,
message: 'Folder created successfully'
})
} catch (error) {
console.error('Create folder error:', error)
if (error instanceof z.ZodError) {
return NextResponse.json(
{ error: 'Invalid input data', details: error.errors },
{ status: 400 }
)
}
return NextResponse.json(
{ error: 'Failed to create folder' },
{ status: 500 }
)
}
}