{"version":3,"sources":["../../src/storage/fileSystemCurriculumAdapter.ts","../../src/storage/supabaseCurriculumAdapter.ts","../../src/storage/factory.ts"],"names":["crypto","path","fs","createClient"],"mappings":"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","file":"index.cjs","sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport type { \n  ICurriculumStorage, \n  SotDocument, \n  LessonArtifactSummary, \n  ProjectStatusReport,\n  PipelineState,\n  ArtifactLifecycleInfo\n} from './types';\nexport function computeContentHash(content: string): string {\n  return 'sha256:' + crypto.createHash('sha256').update(content.trim(), 'utf-8').digest('hex');\n}\n\nexport const STANDARD_SOT_FILES = [\n  'LEARNER_PROFILE.md',\n  'PROJECT_BRIEF.md',\n  'REFERENCE_PACK.md',\n  'PROJECT_GRAPH.json',\n  'HYBRID_GRAPH.json',\n  'CURRICULUM_FRAMEWORK.md',\n  'CONTENT_STYLE_GUIDE.md',\n  'ART_DIRECTION.md',\n  'ALIGNMENT_MATRIX.md',\n];\n\nexport interface FileSystemStorageOptions {\n  baseDir?: string;\n}\n\n/**\n * Atomic single-file write (5-Whys RC-race, 2026-09-13): write to a unique\n * temp file in the SAME directory, then `rename` over the target. On POSIX a\n * rename within a filesystem is atomic — a concurrent reader sees either the\n * old or the new complete file, never a torn write, and two racing writers\n * each land a complete file (last rename wins) instead of interleaved halves.\n * Previously a direct writeFileSync let the double-run race truncate/clobber\n * companion files (deck.json / .html disappeared while the .md survived).\n */\nexport function atomicWriteFileSync(targetPath: string, content: string): void {\n  const dir = path.dirname(targetPath);\n  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n  const tmpPath = path.join(dir, `.${path.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto.randomBytes(4).toString('hex')}.tmp`);\n  try {\n    fs.writeFileSync(tmpPath, content, 'utf-8');\n    fs.renameSync(tmpPath, targetPath);\n  } catch (err) {\n    // Best-effort temp cleanup; never mask the original error.\n    try { if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath); } catch {}\n    throw err;\n  }\n}\n\nexport class FileSystemCurriculumAdapter implements ICurriculumStorage {\n  private baseDir: string;\n\n  constructor(options: FileSystemStorageOptions = {}) {\n    this.baseDir = options.baseDir || path.resolve(process.cwd(), 'output', 'projects');\n  }\n\n  private getProjectDir(projectId: string): string {\n    const raw = (projectId || '').replace('proj_', '');\n    const directPath = path.join(this.baseDir, raw);\n    if (fs.existsSync(directPath)) return directPath;\n    const fullIdPath = path.join(this.baseDir, projectId);\n    if (fs.existsSync(fullIdPath)) return fullIdPath;\n    return directPath;\n  }\n\n  /** Ensures the resolved path stays within the project directory (prevents path traversal). */\n  private assertInsideProject(projectDir: string, targetPath: string): void {\n    const resolvedProject = path.resolve(projectDir);\n    const resolvedTarget = path.resolve(targetPath);\n    if (!resolvedTarget.startsWith(resolvedProject + path.sep) && resolvedTarget !== resolvedProject) {\n      throw new Error(`[FileSystemCurriculumAdapter] Path traversal blocked: ${targetPath} is outside project directory ${projectDir}`);\n    }\n  }\n\n  async projectExists(projectId: string): Promise<boolean> {\n    return fs.existsSync(this.getProjectDir(projectId));\n  }\n\n  async readSotDocument(projectId: string, filename: string): Promise<string | null> {\n    const projectDir = this.getProjectDir(projectId);\n    const possiblePaths = [\n      path.join(projectDir, '_sot', filename),\n      path.join(projectDir, filename),\n    ];\n\n    for (const p of possiblePaths) {\n      if (fs.existsSync(p) && fs.statSync(p).isFile()) {\n        return fs.readFileSync(p, 'utf-8');\n      }\n    }\n    return null;\n  }\n\n  async listSotDocuments(projectId: string): Promise<SotDocument[]> {\n    const projectDir = this.getProjectDir(projectId);\n    const sotDir = path.join(projectDir, '_sot');\n\n    const discoveredFiles = new Set<string>(STANDARD_SOT_FILES);\n    if (fs.existsSync(sotDir)) {\n      try {\n        const diskFiles = fs.readdirSync(sotDir);\n        for (const f of diskFiles) {\n          if (f.startsWith('.') || f.endsWith('.review.json')) continue;\n          const fullPath = path.join(sotDir, f);\n          if (fs.statSync(fullPath).isFile()) {\n            discoveredFiles.add(f);\n          }\n        }\n      } catch {}\n    }\n\n    return Array.from(discoveredFiles).map(filename => {\n      const p = fs.existsSync(path.join(sotDir, filename))\n        ? path.join(sotDir, filename)\n        : (fs.existsSync(path.join(projectDir, filename)) ? path.join(projectDir, filename) : null);\n\n      if (p && fs.existsSync(p)) {\n        const stats = fs.statSync(p);\n        return {\n          name: filename.replace(/\\.(md|json)$/i, '').replace(/_/g, ' '),\n          filename,\n          exists: true,\n          sizeBytes: stats.size\n        };\n      }\n\n      return {\n        name: filename.replace(/\\.(md|json)$/i, '').replace(/_/g, ' '),\n        filename,\n        exists: false,\n        sizeBytes: 0\n      };\n    });\n  }\n\n  async readArtifact(projectId: string, relPathOrIdentifier: string): Promise<string | null> {\n    const projectDir = this.getProjectDir(projectId);\n\n    // Block path traversal attempts\n    const directCandidate = path.join(projectDir, relPathOrIdentifier);\n    this.assertInsideProject(projectDir, directCandidate);\n\n    // 1. Direct file path lookup\n    const possiblePaths = [\n      directCandidate,\n      path.join(projectDir, '_sot', relPathOrIdentifier),\n      path.join(projectDir, 'lessons', relPathOrIdentifier),\n      path.join(projectDir, '_sot', path.basename(relPathOrIdentifier)),\n      path.join(projectDir, 'lessons', path.basename(relPathOrIdentifier)),\n    ];\n\n    for (const p of possiblePaths) {\n      if (fs.existsSync(p) && fs.statSync(p).isFile()) {\n        return fs.readFileSync(p, 'utf-8');\n      }\n    }\n\n    // If relPathOrIdentifier was an explicit filename with extension, don't guess\n    if (relPathOrIdentifier.includes('.md') || relPathOrIdentifier.includes('/')) {\n      return null;\n    }\n\n    // 2. Intelligent Identifier Resolution for query strings (e.g. \"U01_M01_L01 — Giáo án 5E\")\n    const lessonMatch = relPathOrIdentifier.match(/U\\d+_M\\d+_L\\d+/i);\n    if (lessonMatch) {\n      const lessonId = lessonMatch[0].toUpperCase();\n      const lessonDir = path.join(projectDir, 'lessons', lessonId);\n\n      if (fs.existsSync(lessonDir) && fs.statSync(lessonDir).isDirectory()) {\n        const lower = relPathOrIdentifier.toLowerCase();\n        let artifactPrefix = 'LESSON';\n        if (lower.includes('act') || lower.includes('lab') || lower.includes('thực hành')) {\n          artifactPrefix = 'ACT';\n        } else if (lower.includes('quiz') || lower.includes('trắc nghiệm') || lower.includes('đánh giá')) {\n          artifactPrefix = 'QUIZ';\n        } else if (lower.includes('slide') || lower.includes('bài giảng') || lower.includes('trình chiếu')) {\n          artifactPrefix = 'SLIDE';\n        } else if (lower.includes('guide') || lower.includes('hướng dẫn')) {\n          artifactPrefix = 'GUIDE';\n        } else if (lower.includes('wks') || lower.includes('worksheet') || lower.includes('phiếu bài tập')) {\n          artifactPrefix = 'WKS';\n        } else if (lower.includes('handout') || lower.includes('tài liệu')) {\n          artifactPrefix = 'HANDOUT';\n        } else if (lower.includes('code')) {\n          artifactPrefix = 'CODE';\n        } else if (lower.includes('ext') || lower.includes('extension')) {\n          artifactPrefix = 'EXT';\n        }\n\n        const candidateFile = path.join(lessonDir, `${artifactPrefix}_${lessonId}.md`);\n        if (fs.existsSync(candidateFile)) {\n          return fs.readFileSync(candidateFile, 'utf-8');\n        }\n      }\n    }\n\n    return null;\n  }\n\n  async saveArtifact(projectId: string, relPath: string, content: string): Promise<void> {\n    const projectDir = this.getProjectDir(projectId);\n    const targetPath = path.join(projectDir, relPath);\n    this.assertInsideProject(projectDir, targetPath);\n    const targetDir = path.dirname(targetPath);\n\n    if (!fs.existsSync(targetDir)) {\n      fs.mkdirSync(targetDir, { recursive: true });\n    }\n\n    // Version history (P2): ghi đè file đã tồn tại → chép bản cũ vào .history/ trước (giữ tối đa 10 bản gần nhất)\n    if (fs.existsSync(targetPath)) {\n      try {\n        const oldContent = fs.readFileSync(targetPath, 'utf-8');\n        if (oldContent !== content) {\n          const historyDir = path.join(projectDir, '.history', relPath);\n          fs.mkdirSync(historyDir, { recursive: true });\n          atomicWriteFileSync(path.join(historyDir, `${Date.now()}.md`), oldContent);\n          const versions = fs.readdirSync(historyDir).filter((f) => f.endsWith('.md')).sort();\n          while (versions.length > 10) {\n            fs.unlinkSync(path.join(historyDir, versions.shift() as string));\n          }\n        }\n      } catch (histErr: any) {\n        // History failure KHÔNG chặn ghi chính — nhưng không âm thầm: log rõ\n        console.warn('[FileSystemCurriculumAdapter] version history snapshot failed:', histErr?.message || histErr);\n      }\n    }\n\n    atomicWriteFileSync(targetPath, content);\n\n    // Phase 2: Automatic entity sidecar generation alongside markdown\n    // Also auto-sync to lessons/ directory if this is a lesson artifact (e.g. _content/U01/SLIDE_U01_M01_L01.md)\n    const filename = path.basename(relPath);\n    const match = filename.match(/(LESSON|ACT|QUIZ|SLIDE|GUIDE|HANDOUT|WKS|EXT)_(U\\d+_M\\d+_L\\d+)\\.md/i);\n    if (match) {\n      const lessonId = match[2].toUpperCase();\n      atomicWriteFileSync(path.join(projectDir, 'lessons', lessonId, filename), content);\n\n      // Also sync to legacy _content/U01_M01_L01/ folder if it exists\n      const legacyContentDir = path.join(projectDir, '_content', lessonId);\n      if (fs.existsSync(legacyContentDir)) {\n        atomicWriteFileSync(path.join(legacyContentDir, filename), content);\n      }\n    }\n  }\n\n  async listLessons(projectId: string): Promise<LessonArtifactSummary[]> {\n    const lessonsDir = path.join(this.getProjectDir(projectId), 'lessons');\n    if (!fs.existsSync(lessonsDir)) return [];\n\n    const lessonFolders = fs.readdirSync(lessonsDir).filter(f => !f.startsWith('.'));\n    return lessonFolders.map(folder => {\n      const lDir = path.join(lessonsDir, folder);\n      const isDir = fs.statSync(lDir).isDirectory();\n      if (!isDir) {\n        return {\n          lessonId: folder,\n          artifactsCount: 0,\n          isComplete: false,\n          artifacts: []\n        };\n      }\n\n      const artifacts = fs.readdirSync(lDir).filter(f => !f.startsWith('.'));\n      return {\n        lessonId: folder,\n        artifactsCount: artifacts.length,\n        isComplete: artifacts.length >= 4,\n        artifacts\n      };\n    });\n  }\n\n  async getProjectStatus(projectId: string): Promise<ProjectStatusReport> {\n    const sotList = await this.listSotDocuments(projectId);\n    const lessons = await this.listLessons(projectId);\n\n    const completedCount = lessons.filter(l => l.isComplete).length;\n    const totalLessons = lessons.length || 4;\n    const progressPercent = Math.round((completedCount / totalLessons) * 100);\n\n    const sotTable = sotList.map(doc => `| \\`${doc.filename}\\` | ${doc.exists ? '✅ Sẵn sàng' : '❌ Chưa có'} |`).join('\\n');\n    const lessonTable = lessons.length > 0 \n      ? lessons.map(l => `| **${l.lessonId}** | ${l.artifactsCount}/4 Artifacts | ${l.isComplete ? '✅ Hoàn tất' : '⏳ Đang tạo sinh'} | ${l.artifacts.join(', ') || '-'} |`).join('\\n')\n      : '| Chưa có bài học nào trên đĩa cứng | 0/4 | ⏳ Chờ chạy | - |';\n\n    const rawMarkdownReport = `## 📊 BÁO CÁO TRẠNG THÁI DỰ ÁN: \\`${projectId.toUpperCase()}\\`\n\n### 1. Nền tảng Tài liệu (SOT Readiness)\n| Tài liệu SOT | Trạng thái |\n|---|:---:|\n${sotTable}\n\n### 2. Danh mục Bài học & Học liệu (Lessons & Artifacts Matrix)\n| Mã bài học | Số lượng Artifact | Trạng thái | Danh sách Artifact đã tạo |\n|---|:---:|:---:|---|\n${lessonTable}\n\n**Tiến độ tổng thể:** ${completedCount}/${totalLessons} bài học (${progressPercent}%)\n\n### 3. Đề xuất Hành động Tiếp theo:\n- Sử dụng lệnh \\`/create-lesson <id>\\` để tạo sinh các bài học tiếp theo trong pipeline.\n- Sử dụng lệnh \\`/audit-quality\\` để chạy kiểm thử tiêu chuẩn Bloom và Alignment Matrix.`;\n\n    return {\n      projectId,\n      sotReadiness: sotList,\n      lessons,\n      completedCount,\n      totalLessons,\n      progressPercent,\n      rawMarkdownReport\n    };\n  }\n\n  async getPipelineState(projectId: string): Promise<PipelineState> {\n    const projectDir = this.getProjectDir(projectId);\n    const stateFile = path.join(projectDir, '_pipeline', 'state.json');\n\n    if (fs.existsSync(stateFile)) {\n      try {\n        const raw = fs.readFileSync(stateFile, 'utf-8');\n        const parsed = JSON.parse(raw);\n        if (parsed && typeof parsed === 'object' && parsed.tasks) {\n          return parsed as PipelineState;\n        }\n      } catch (err) {\n        console.warn(`[FileSystemCurriculumAdapter] Error reading pipeline state for ${projectId}:`, err);\n      }\n    }\n\n    // Default empty pipeline state\n    return {\n      projectId,\n      updatedAt: new Date().toISOString(),\n      tasks: {}\n    };\n  }\n\n  async savePipelineState(projectId: string, state: PipelineState): Promise<void> {\n    const projectDir = this.getProjectDir(projectId);\n    const pipelineDir = path.join(projectDir, '_pipeline');\n\n    if (!fs.existsSync(pipelineDir)) {\n      fs.mkdirSync(pipelineDir, { recursive: true });\n    }\n\n    const stateFile = path.join(pipelineDir, 'state.json');\n    state.updatedAt = new Date().toISOString();\n    atomicWriteFileSync(stateFile, JSON.stringify(state, null, 2));\n  }\n\n  async updateArtifactState(\n    projectId: string,\n    taskId: string,\n    artifactType: string,\n    update: Partial<ArtifactLifecycleInfo>\n  ): Promise<PipelineState> {\n    const current = await this.getPipelineState(projectId);\n    if (!current.tasks[taskId]) {\n      current.tasks[taskId] = {};\n    }\n\n    const existingInfo = current.tasks[taskId][artifactType] || {\n      state: 'pending',\n    };\n\n    current.tasks[taskId][artifactType] = {\n      ...existingInfo,\n      ...update,\n    };\n\n    await this.savePipelineState(projectId, current);\n    return current;\n  }\n\n  /** Disk adapter: purge = rm the file (best-effort, mirrors cloud deleteArtifact). */\n  async deleteArtifact(projectId: string, relPath: string): Promise<void> {\n    try {\n      const projectDir = this.getProjectDir(projectId);\n      const targetPath = path.join(projectDir, relPath);\n      this.assertInsideProject(projectDir, targetPath);\n      if (fs.existsSync(targetPath)) fs.rmSync(targetPath, { force: true });\n    } catch { /* best-effort */ }\n  }\n}\n","import { createClient, type SupabaseClient } from '@supabase/supabase-js';\nimport type { MilestoneCurriculumBundle } from '../pipeline';\nimport type { \n  ICurriculumStorage, \n  SotDocument, \n  LessonArtifactSummary, \n  ProjectStatusReport \n} from './types';\nimport { STANDARD_SOT_FILES } from './fileSystemCurriculumAdapter';\n\nexport interface SupabaseStorageConfig {\n  supabaseUrl?: string;\n  supabaseServiceRoleKey?: string;\n  bucketName?: string;\n  client?: SupabaseClient;\n}\n\n/**\n * Supabase Curriculum Adapter — Syncs Markdown artifacts to Storage & Database\n * Implements ICurriculumStorage for multi-tenant Cloud deployment (Vercel, Netlify, Cloudflare, etc.).\n */\nexport class SupabaseCurriculumAdapter implements ICurriculumStorage {\n  private client: SupabaseClient;\n  private bucketName: string;\n\n  constructor(config: SupabaseStorageConfig = {}) {\n    this.bucketName = config.bucketName || process.env.SUPABASE_STORAGE_BUCKET || 'course-materials';\n\n    if (config.client) {\n      this.client = config.client;\n    } else {\n      const url = config.supabaseUrl || process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL || '';\n      const key =\n        config.supabaseServiceRoleKey ||\n        process.env.SUPABASE_SERVICE_ROLE_KEY ||\n        process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ||\n        '';\n\n      if (!url || !key) {\n        throw new Error('Supabase URL or Key is missing in SupabaseCurriculumAdapter');\n      }\n\n      this.client = createClient(url, key);\n    }\n  }\n\n  async projectExists(projectId: string): Promise<boolean> {\n    try {\n      const { data, error } = await this.client.storage\n        .from(this.bucketName)\n        .list(projectId, { limit: 5 });\n      return !error && !!data && data.length > 0;\n    } catch {\n      return false;\n    }\n  }\n\n  async readSotDocument(projectId: string, filename: string): Promise<string | null> {\n    const paths = [\n      `${projectId}/_sot/${filename}`,\n      `${projectId}/${filename}`,\n      `${projectId}/_designer/${filename}`,\n      `${projectId}/_analyst/${filename}`\n    ];\n    for (const p of paths) {\n      try {\n        const { data, error } = await this.client.storage.from(this.bucketName).download(p);\n        if (!error && data) {\n          return await data.text();\n        }\n      } catch {}\n    }\n    return null;\n  }\n\n  async listSotDocuments(projectId: string): Promise<SotDocument[]> {\n    const discoveredFiles = new Set<string>(STANDARD_SOT_FILES);\n    try {\n      const { data, error } = await this.client.storage\n        .from(this.bucketName)\n        .list(`${projectId}/_sot`);\n      if (!error && data) {\n        for (const item of data) {\n          if (item.name && !item.name.startsWith('.') && !item.name.endsWith('.review.json')) {\n            discoveredFiles.add(item.name);\n          }\n        }\n      }\n    } catch {}\n\n    const results: SotDocument[] = [];\n    for (const filename of discoveredFiles) {\n      const content = await this.readSotDocument(projectId, filename);\n      results.push({\n        name: filename.replace(/\\.(md|json)$/i, '').replace(/_/g, ' '),\n        filename,\n        exists: !!content,\n        content: content || undefined,\n        sizeBytes: content ? content.length : 0\n      });\n    }\n    return results;\n  }\n\n  async readArtifact(projectId: string, relPathOrIdentifier: string): Promise<string | null> {\n    const cleanPath = relPathOrIdentifier.replace(/^\\//, '');\n\n    // 1. Direct path lookup attempts\n    const possiblePaths = [\n      `${projectId}/${cleanPath}`,\n      `${projectId}/_sot/${cleanPath}`,\n      `${projectId}/_content/${cleanPath}`,\n      `${projectId}/lessons/${cleanPath}`,\n      `${projectId}/_sot/${cleanPath.split('/').pop()}`,\n      `${projectId}/lessons/${cleanPath.split('/').pop()}`,\n    ];\n\n    for (const p of possiblePaths) {\n      try {\n        const { data, error } = await this.client.storage.from(this.bucketName).download(p);\n        if (!error && data) {\n          return await data.text();\n        }\n      } catch {}\n    }\n\n    // If relPathOrIdentifier was an explicit filename with extension or path, don't guess\n    if (relPathOrIdentifier.includes('.md') || relPathOrIdentifier.includes('.json') || relPathOrIdentifier.includes('/')) {\n      return null;\n    }\n\n    // 2. Intelligent Identifier Resolution (e.g. \"U01_M01_L01 — Giáo án 5E\" or \"U01_M01_L01\")\n    const lessonMatch = relPathOrIdentifier.match(/U\\d+_M\\d+_L\\d+/i);\n    if (lessonMatch) {\n      const lessonId = lessonMatch[0].toUpperCase();\n      const unitCode = lessonId.split('_')[0] || 'U01';\n      const lower = relPathOrIdentifier.toLowerCase();\n\n      let artifactPrefix: string | null = null;\n      if (lower.includes('act') || lower.includes('lab') || lower.includes('thực hành')) {\n        artifactPrefix = 'ACT';\n      } else if (lower.includes('quiz') || lower.includes('trắc nghiệm') || lower.includes('đánh giá')) {\n        artifactPrefix = 'QUIZ';\n      } else if (lower.includes('slide') || lower.includes('bài giảng') || lower.includes('trình chiếu')) {\n        artifactPrefix = 'SLIDE';\n      } else if (lower.includes('guide') || lower.includes('hướng dẫn')) {\n        artifactPrefix = 'GUIDE';\n      } else if (lower.includes('wks') || lower.includes('worksheet') || lower.includes('phiếu bài tập')) {\n        artifactPrefix = 'WKS';\n      } else if (lower.includes('handout') || lower.includes('tài liệu')) {\n        artifactPrefix = 'HANDOUT';\n      } else if (lower.includes('code')) {\n        artifactPrefix = 'CODE';\n      } else if (lower.includes('ext') || lower.includes('extension') || lower.includes('mở rộng')) {\n        artifactPrefix = 'EXT';\n      } else if (lower.includes('exp') || lower.includes('exposition') || lower.includes('tự học') || lower.includes('kiến thức nền')) {\n        artifactPrefix = 'EXPOSITION';\n      } else if (lower.includes('rubric')) {\n        artifactPrefix = 'RUBRIC';\n      } else if (lower.includes('bom')) {\n        artifactPrefix = 'BOM';\n      } else if (lower.includes('lesson') || lower.includes('giáo án') || lower.includes('5e')) {\n        artifactPrefix = 'LESSON';\n      }\n\n      if (!artifactPrefix) {\n        return null;\n      }\n\n      const candidatePaths = [\n        `${projectId}/_content/${unitCode}/${artifactPrefix}_${lessonId}.md`,\n        `${projectId}/lessons/${lessonId}/${artifactPrefix}_${lessonId}.md`,\n        `${projectId}/${artifactPrefix}_${lessonId}.md`,\n      ];\n\n      for (const p of candidatePaths) {\n        try {\n          const { data, error } = await this.client.storage.from(this.bucketName).download(p);\n          if (!error && data) {\n            return await data.text();\n          }\n        } catch {}\n      }\n    }\n\n    return null;\n  }\n\n  async saveArtifact(projectId: string, relPath: string, content: string): Promise<void> {\n    const fullPath = `${projectId}/${relPath.replace(/^\\//, '')}`;\n    const { error } = await this.client.storage\n      .from(this.bucketName)\n      .upload(fullPath, Buffer.from(content, 'utf-8'), {\n        contentType: 'text/markdown',\n        upsert: true,\n      });\n\n    if (error) {\n      throw new Error(`Failed to upload artifact to Supabase Storage: ${error.message}`);\n    }\n\n    // Optional DB Upsert for fast indexed searching if artifacts table exists\n    try {\n      await this.client.from('curriculum_artifacts').upsert({\n        project_id: projectId,\n        rel_path: relPath,\n        content: content,\n        updated_at: new Date().toISOString(),\n      }, { onConflict: 'project_id,rel_path' });\n    } catch {\n      // Ignore if table not yet migrated\n    }\n  }\n\n  /**\n   * Split-brain root-cause fix (2026-09-14): purge must reach the cloud copy\n   * too. Removes the storage object AND the indexed `curriculum_artifacts`\n   * row (the row is what `readArtifact`-style indexed readers resolve first).\n   * Best-effort / no-throw per the interface contract.\n   */\n  async deleteArtifact(projectId: string, relPath: string): Promise<void> {\n    const fullPath = `${projectId}/${relPath.replace(/^\\//, '')}`;\n    try {\n      await this.client.storage.from(this.bucketName).remove([fullPath]);\n    } catch { /* object may not exist — fine */ }\n    try {\n      await this.client\n        .from('curriculum_artifacts')\n        .delete()\n        .match({ project_id: projectId, rel_path: relPath });\n    } catch { /* table may not exist — fine */ }\n  }\n\n  async listLessons(projectId: string): Promise<LessonArtifactSummary[]> {\n    const summaries: LessonArtifactSummary[] = [];\n    const processedLessons = new Set<string>();\n\n    try {\n      // 1. Scan _content/ folders (e.g. _content/U01/, _content/U02/)\n      const { data: unitDirs } = await this.client.storage\n        .from(this.bucketName)\n        .list(`${projectId}/_content`);\n\n      if (unitDirs) {\n        for (const u of unitDirs) {\n          const { data: files } = await this.client.storage\n            .from(this.bucketName)\n            .list(`${projectId}/_content/${u.name}`);\n\n          if (files) {\n            const lessonMap: Record<string, string[]> = {};\n            files.forEach(f => {\n              const m = f.name.match(/U\\d+_M\\d+_L\\d+/i);\n              if (m) {\n                const lid = m[0].toUpperCase();\n                lessonMap[lid] = lessonMap[lid] || [];\n                lessonMap[lid].push(f.name);\n              }\n            });\n\n            for (const [lid, arts] of Object.entries(lessonMap)) {\n              if (!processedLessons.has(lid)) {\n                processedLessons.add(lid);\n                summaries.push({\n                  lessonId: lid,\n                  artifactsCount: arts.length,\n                  isComplete: arts.length >= 4,\n                  artifacts: arts,\n                });\n              }\n            }\n          }\n        }\n      }\n\n      // 2. Scan lessons/ folders (legacy / alternate structure)\n      const { data: lessonDirs } = await this.client.storage\n        .from(this.bucketName)\n        .list(`${projectId}/lessons`);\n\n      if (lessonDirs) {\n        for (const dir of lessonDirs) {\n          if (!processedLessons.has(dir.name)) {\n            const { data: files } = await this.client.storage\n              .from(this.bucketName)\n              .list(`${projectId}/lessons/${dir.name}`);\n            \n            const artifacts = (files || []).map(f => f.name).filter(n => !n.startsWith('.'));\n            processedLessons.add(dir.name);\n            summaries.push({\n              lessonId: dir.name,\n              artifactsCount: artifacts.length,\n              isComplete: artifacts.length >= 4,\n              artifacts\n            });\n          }\n        }\n      }\n    } catch {\n      // Fallback\n    }\n\n    return summaries;\n  }\n\n  async getProjectStatus(projectId: string): Promise<ProjectStatusReport> {\n    const sotList = await this.listSotDocuments(projectId);\n    const lessons = await this.listLessons(projectId);\n\n    const completedCount = lessons.filter(l => l.isComplete).length;\n    const totalLessons = lessons.length || 4;\n    const progressPercent = Math.round((completedCount / totalLessons) * 100);\n\n    const sotTable = sotList.map(doc => `| \\`${doc.filename}\\` | ${doc.exists ? '✅ Sẵn sàng' : '❌ Chưa có'} |`).join('\\n');\n    const lessonTable = lessons.length > 0 \n      ? lessons.map(l => `| **${l.lessonId}** | ${l.artifactsCount}/4 Artifacts | ${l.isComplete ? '✅ Hoàn tất' : '⏳ Đang tạo sinh'} | ${l.artifacts.join(', ') || '-'} |`).join('\\n')\n      : '| Chưa có bài học nào trên cloud storage | 0/4 | ⏳ Chờ chạy | - |';\n\n    const rawMarkdownReport = `## 📊 BÁO CÁO TRẠNG THÁI DỰ ÁN (CLOUD): \\`${projectId.toUpperCase()}\\`\n\n### 1. Nền tảng Tài liệu (SOT Readiness)\n| Tài liệu SOT | Trạng thái |\n|---|:---:|\n${sotTable}\n\n### 2. Danh mục Bài học & Học liệu (Lessons & Artifacts Matrix)\n| Mã bài học | Số lượng Artifact | Trạng thái | Danh sách Artifact đã tạo |\n|---|:---:|:---:|---|\n${lessonTable}\n\n**Tiến độ tổng thể:** ${completedCount}/${totalLessons} bài học (${progressPercent}%)`;\n\n    return {\n      projectId,\n      sotReadiness: sotList,\n      lessons,\n      completedCount,\n      totalLessons,\n      progressPercent,\n      rawMarkdownReport\n    };\n  }\n\n  /**\n   * Uploads a complete milestone bundle (Markdown files) to Supabase Storage\n   */\n  async uploadMilestoneBundle(\n    projectSlug: string,\n    bundle: MilestoneCurriculumBundle\n  ): Promise<{ lessonUrl?: string; activityUrl?: string; handoutUrl?: string }> {\n    const basePath = `${projectSlug}/${bundle.milestoneId}`;\n\n    const uploads = [\n      {\n        path: `${basePath}/LESSON.md`,\n        content: bundle.lessonMarkdown,\n        type: 'text/markdown',\n      },\n      {\n        path: `${basePath}/ACT.md`,\n        content: bundle.activityMarkdown,\n        type: 'text/markdown',\n      },\n      {\n        path: `${basePath}/HANDOUT.md`,\n        content: bundle.handoutMarkdown,\n        type: 'text/markdown',\n      },\n    ];\n\n    const results: Record<string, string> = {};\n\n    for (const item of uploads) {\n      const { data, error } = await this.client.storage\n        .from(this.bucketName)\n        .upload(item.path, Buffer.from(item.content, 'utf-8'), {\n          contentType: item.type,\n          upsert: true,\n        });\n\n      if (!error && data) {\n        const { data: publicUrlData } = this.client.storage.from(this.bucketName).getPublicUrl(item.path);\n        results[item.path] = publicUrlData.publicUrl;\n      }\n    }\n\n    return {\n      lessonUrl: results[`${basePath}/LESSON.md`],\n      activityUrl: results[`${basePath}/ACT.md`],\n      handoutUrl: results[`${basePath}/HANDOUT.md`],\n    };\n  }\n\n  async getPipelineState(projectId: string): Promise<import('./types').PipelineState> {\n    const p = `${projectId}/_pipeline/state.json`;\n    try {\n      const { data, error } = await this.client.storage.from(this.bucketName).download(p);\n      if (!error && data) {\n        const text = await data.text();\n        return JSON.parse(text);\n      }\n    } catch {}\n\n    return {\n      projectId,\n      updatedAt: new Date().toISOString(),\n      tasks: {}\n    };\n  }\n\n  async savePipelineState(projectId: string, state: import('./types').PipelineState): Promise<void> {\n    const p = `${projectId}/_pipeline/state.json`;\n    state.updatedAt = new Date().toISOString();\n    await this.client.storage.from(this.bucketName).upload(p, Buffer.from(JSON.stringify(state, null, 2), 'utf-8'), {\n      contentType: 'application/json',\n      upsert: true,\n    });\n  }\n\n  async updateArtifactState(\n    projectId: string,\n    taskId: string,\n    artifactType: string,\n    update: Partial<import('./types').ArtifactLifecycleInfo>\n  ): Promise<import('./types').PipelineState> {\n    const current = await this.getPipelineState(projectId);\n    if (!current.tasks[taskId]) {\n      current.tasks[taskId] = {};\n    }\n    current.tasks[taskId][artifactType] = {\n      ...(current.tasks[taskId][artifactType] || { state: 'pending' }),\n      ...update,\n    };\n    await this.savePipelineState(projectId, current);\n    return current;\n  }\n}\n","import type { ICurriculumStorage } from './types';\nimport { FileSystemCurriculumAdapter, FileSystemStorageOptions } from './fileSystemCurriculumAdapter';\nimport { SupabaseCurriculumAdapter, SupabaseStorageConfig } from './supabaseCurriculumAdapter';\n\nexport interface StorageFactoryOptions {\n  provider?: 'filesystem' | 'supabase' | 'auto';\n  fileSystemOptions?: FileSystemStorageOptions;\n  supabaseConfig?: SupabaseStorageConfig;\n}\n\n/**\n * Creates and returns the appropriate ICurriculumStorage instance based on environment or explicit config.\n */\nexport function createCurriculumStorage(options: StorageFactoryOptions = {}): ICurriculumStorage {\n  const provider = options.provider || process.env.CURRICULUM_STORAGE_PROVIDER || 'auto';\n\n  if (provider === 'supabase') {\n    return new SupabaseCurriculumAdapter(options.supabaseConfig);\n  }\n\n  if (provider === 'auto') {\n    const hasSupabase = Boolean(\n      (process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL) &&\n      (process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) &&\n      process.env.STORAGE_USE_SUPABASE === 'true'\n    );\n\n    if (hasSupabase) {\n      try {\n        return new SupabaseCurriculumAdapter(options.supabaseConfig);\n      } catch (e) {\n        console.warn('⚠️ Falling back to FileSystemCurriculumAdapter due to Supabase initialization error:', e);\n      }\n    }\n  }\n\n  return new FileSystemCurriculumAdapter(options.fileSystemOptions);\n}\n"]}