export const scenarios=[
 {title:'1. Каталог и карточка',goal:'Карточка услуги по идентификатору: параметры пути и отсутствие записи.',tip:'Получите заявку № 1, затем неизвестный номер. 404 — ожидаемый ответ, а не поломка мастерской.',variants:[['Найти № 1','GET','/api/jobs/1'],['Нет № 999','GET','/api/jobs/999'],['Неверный ID','GET','/api/jobs/abc']]},
 {title:'2. Создание и валидация',goal:'Форма заявки: успешное сохранение, ошибки полей и синтаксиса JSON.',tip:'Запись добавляется только в память этой мастерской. В списке её можно найти, после сброса она исчезнет.',variants:[['Создать заявку','POST','/api/jobs','{"title":"Настроить API сайта","budget":15000}'],['Ошибки полей','POST','/api/jobs','{"title":"A","budget":-1}'],['Плохой JSON','POST','/api/jobs','{"title":']]},
 {title:'3. Цепочка middleware',goal:'Как общие действия выполняются до и после обработчика.',tip:'Смотрите журнал этапов и X-Request-Id в заголовках. Server-Timing измеряет формирование ответа, для SSE это не вся длительность потока.',variants:[['Проверить health','GET','/api/health']]},
 {title:'4. Ошибки и контракт',goal:'Одинаковая форма ошибок для клиента и непубличные детали исключения.',tip:'500 здесь вызван специально. Стек и текст внутреннего исключения не попадают в JSON. Неизвестный маршрут возвращает 404.',variants:[['Учебная 500','GET','/api/failure'],['Маршрут 404','GET','/api/missing']]},
 {title:'5. Поиск и страницы',goal:'Список заявок для админки: фильтр, размер страницы, пустое состояние.',tip:'Измените page, limit, q или status прямо в пути. Размер страницы — 1–10. Поиск по названию, статус all/open/done.',variants:[['Страница 1','GET','/api/jobs?page=1&limit=3&status=open'],['Страница 2','GET','/api/jobs?page=2&limit=3&status=open'],['Ничего не найдено','GET','/api/jobs?q=несуществующая'],['Ошибка границ','GET','/api/jobs?limit=1000']]},
 {title:'6. Доступ к своей записи',goal:'Разница между отсутствием идентичности и запретом конкретной операции.',tip:'demo-anna — открытый учебный токен. Он известен всем и НЕ защищает настоящие данные. owner назначается на сервере, а не берётся из тела.',variants:[['Своя · 200','GET','/api/private/jobs/1',null,'demo-anna'],['Без токена · 401','GET','/api/private/jobs/1'],['Чужая · 403','GET','/api/private/jobs/2',null,'demo-anna']]},
 {title:'7. Лимит тела и CORS',goal:'Слишком большое тело отклоняется до JSON-разбора; заголовки CORS видны отдельно.',tip:'1024 — предел байт UTF-8, а не символов. Preflight показывает ответ middleware; app.request не воспроизводит сетевые ограничения браузера.',variants:[['Тело > 1024 байт','POST','/api/jobs',JSON.stringify({title:'Я'.repeat(600),budget:1})],['CORS preflight','OPTIONS','/api/jobs']]},
 {title:'8. Поток прогресса SSE',goal:'Читать результат порциями, показывать прогресс и останавливать чтение.',tip:'Настоящий ReadableStream и события SSE. Порции учебные, задержка 280 мс задана явно. Отмена закрывает читателя; это не отмена задания в BullMQ.',variants:[['Пять этапов','GET','/api/progress?steps=5'],['Восемь этапов','GET','/api/progress?steps=8']]},
 {title:'9. Один router, два режима',goal:'Сопоставить app.request с настоящим Node HTTP из архива.',tip:'Здесь router выполняется в браузере. Скачайте архив и запустите npm start: curl обращается к тому же API через реальный TCP/HTTP. Эта кнопка не проверяет ваш сервер.',variants:[['Контракт health','GET','/api/health'],['Контракт списка','GET','/api/jobs?limit=2']]}
];
export function requestCode({path,method,body,token}){
 const init={method,headers:{'Content-Type':'application/json'}};if(token)init.headers.Authorization=`Bearer ${token}`;if(method==='POST')init.body=body;if(method==='OPTIONS'){init.headers.Origin='https://demo.example';init.headers['Access-Control-Request-Method']='POST';init.headers['Access-Control-Request-Headers']='content-type';}
 return `// Выполнить из корня распакованного проекта после npm ci\n// Сохраните как request-example.mjs, затем node request-example.mjs\nimport { createApi } from './src/router.js';\nconst app = createApi();\nconst response = await app.request(${JSON.stringify(path)}, ${JSON.stringify(init,null,2)});\nconsole.log(response.status, Object.fromEntries(response.headers));\nconsole.log(await response.text());\n// HTTP-вариант после npm start:\n// const response = await fetch('http://127.0.0.1:8502' + ${JSON.stringify(path)}, ${JSON.stringify(init)});\n`;
}
