From e4a724bff452d7e83d78bdb53ec9cdd3a9814f1a Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 3 May 2026 13:40:00 +0700 Subject: [PATCH] 690503:1340 Update workflow #05 --- frontend/.gitignore | 3 +++ .../components/workflows/__tests__/dsl-editor.test.tsx | 4 ++++ frontend/components/workflows/dsl-editor.tsx | 9 ++++++++- frontend/package.json | 4 +++- frontend/proxy.ts | 2 ++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/frontend/.gitignore b/frontend/.gitignore index 5f52b47..25d4cb5 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -17,6 +17,9 @@ # production /build +# Generated Monaco Editor self-hosted assets (สร้างใหม่อัตโนมัติจาก npm postinstall) +/public/monaco-vs + # misc .DS_Store *.pem diff --git a/frontend/components/workflows/__tests__/dsl-editor.test.tsx b/frontend/components/workflows/__tests__/dsl-editor.test.tsx index 8038695..7fce464 100644 --- a/frontend/components/workflows/__tests__/dsl-editor.test.tsx +++ b/frontend/components/workflows/__tests__/dsl-editor.test.tsx @@ -15,6 +15,10 @@ vi.mock('@monaco-editor/react', () => ({ onChange={(e) => onChange?.(e.target.value)} /> ), + // เพิ่ม loader mock เพื่อรองรับ loader.config() call ใน dsl-editor.tsx + loader: { + config: vi.fn(), + }, })); // Mock next-themes diff --git a/frontend/components/workflows/dsl-editor.tsx b/frontend/components/workflows/dsl-editor.tsx index 7faf7cf..09661d2 100644 --- a/frontend/components/workflows/dsl-editor.tsx +++ b/frontend/components/workflows/dsl-editor.tsx @@ -1,3 +1,5 @@ +// File: components/workflows/dsl-editor.tsx +// Change Log: 2026-05-03 — แก้ CSP violation โดยเปลี่ยนจาก CDN เป็น self-hosted Monaco assets 'use client'; import { useState, useRef, useEffect } from 'react'; @@ -5,11 +7,16 @@ import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { CheckCircle, AlertCircle, Play, Loader2 } from 'lucide-react'; -import Editor, { OnMount } from '@monaco-editor/react'; +import Editor, { OnMount, loader } from '@monaco-editor/react'; import { workflowApi } from '@/lib/api/workflows'; import { ValidationResult } from '@/types/workflow'; import { useTheme } from 'next-themes'; +// กำหนดให้ Monaco โหลด assets จาก self-hosted path แทน cdn.jsdelivr.net +// เพื่อผ่าน CSP directive: style-src 'self' 'unsafe-inline' +loader.config({ paths: { vs: '/monaco-vs' } }); + + interface DSLEditorProps { initialValue?: string; onChange?: (value: string) => void; diff --git a/frontend/package.json b/frontend/package.json index 2641997..38cb68d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,7 +12,9 @@ "test": "vitest", "test:watch": "vitest --watch", "test:coverage": "vitest run --coverage", - "test:debug": "vitest --inspect-brk --no-file-parallelism" + "test:debug": "vitest --inspect-brk --no-file-parallelism", + "copy-monaco-assets": "node -e \"const fs=require('fs');const src='node_modules/monaco-editor/min/vs';const dst='public/monaco-vs';if(!fs.existsSync(dst)){fs.cpSync(src,dst,{recursive:true});console.log('Monaco assets copied')}else{console.log('Monaco assets already exist')}\"", + "postinstall": "npm run copy-monaco-assets" }, "dependencies": { "@hookform/resolvers": "3.9.0", diff --git a/frontend/proxy.ts b/frontend/proxy.ts index 8562ad5..3e76edf 100644 --- a/frontend/proxy.ts +++ b/frontend/proxy.ts @@ -98,6 +98,8 @@ export default auth((req) => { "img-src 'self' blob: data: https:", "font-src 'self' data:", `connect-src 'self' ws: wss: ${connectSrcApi}`, + // Monaco Editor Web Workers ต้องการ blob: URL สำหรับ inline workers + "worker-src 'self' blob:", "object-src 'none'", "base-uri 'self'", "form-action 'self'",