Знакомство с AdonisJS

MMaximilian Schwarzmüller
Computing/SoftwareSmall Business/StartupsInternet Technology

Transcript

00:00:00Спасибо.
00:00:30Всем привет. Добро пожаловать на сегодняшний стрим об Adonis.js, должно быть интересно. Это фреймворк и библиотека, которыми я никогда раньше не пользовался. Я всегда хотел попробовать, поэтому подумал, почему бы не сделать это сегодня.
00:01:00Дайте мне быстро устроиться.
00:01:07Надеюсь, у вас все хорошо. Спасибо, что присоединились.
00:01:16Давайте погрузимся. Да. Привет. Привет всем. Сегодня я хочу погрузиться в Adonis и немного изучить его. Просто ради интереса, потому что Adonis.js — это фреймворк JavaScript, который сильно отличается от других фреймворков.
00:01:38И, конечно, мы уже не в 2019 году. Так что можно поспорить, насколько важны фреймворки JavaScript в наши дни, верно? Дни войн фреймворков прошли. Те дни, когда у нас появлялся новый фреймворк каждый день.
00:01:54А сегодня всё крутится вокруг ИИ. Но поскольку в наши дни всё связано с ИИ, я решил, почему бы не провести прямой эфир, где мы рассмотрим что-то, что совершенно не связано с ИИ.
00:02:08Adonis — довольно интересный фреймворк и библиотека. Как я уже сказал, я никогда с ним не работал, но я о нем знаю. Я довольно долго следил за ним.
00:02:20И, в конце концов, это Laravel для JavaScript. Это мое понимание. Это мое понимание Adonis. Это фулстек-фреймворк, и он существовал еще до того, как React-фреймворки стали фулстек-решениями.
00:02:40Так что, я не уверен, был ли он выпущен до того, как у нас появился Next.js, но я бы сказал, еще до того, как Next.js стал суперпопулярным и всё такое.
00:02:51И, да, в нем много интересного. Моя идея сегодня — просто пройтись по этому официальному руководству, посмотреть, что внутри, немного поиграться с ним и узнать, что это такое и как оно работает.
00:03:10Так, у меня был комментарий по поводу новой квоты для компьютеров в планах Google AI. Думаю, я что-то читал об этом. Внимательно не изучал, так что ничего не могу сказать.
00:03:24Вау, это довольно серьезно. Посмотрим. Что такое Adonis? Это бэкенд-ориентированный, типобезопасный фреймворк. Сейчас он бэкенд-ориентированный, но я знаю, что у него есть фулстек-возможности.
00:03:37Вы можете отрисовывать представления с его помощью, так же как с Laravel, если знаете, что это такое.
00:03:42Для создания веб-приложений с Node.js и TypeScript, он предоставляет основные строительные блоки для написания и поддержки полноценных бэкендов, избавляя от необходимости в сторонних сервисах.
00:03:52Да, потому что, как я уже упоминал, как и Laravel, это не просто фулстек-фреймворк вроде Next.js, который по сути дает вам возможности для отрисовки React-компонентов на сервере.
00:04:06Что является довольно грубым описанием, но да, это основная идея Next.js, можно сказать.
00:04:12У них есть маршрутизация и всё такое, но Adonis, как и Laravel, дает вам больше.
00:04:16Он поставляется со встроенной аутентификацией, так что вам не нужна дополнительная библиотека для этого.
00:04:21Он поставляется со встроенной поддержкой загрузки файлов, кэширования, ограничения частоты запросов и многим другим.
00:04:26У него есть собственный ORM, объектно-реляционное отображение, кажется, так это расшифровывается.
00:04:33Это собственная обертка над SQL-базой данных и так далее.
00:04:35Так что довольно мощный и способный инструмент.
00:04:38Идея в том, что вам нужен только Adonis.js, если вы хотите создать фулстек-приложение, и вам не нужно слишком много других зависимостей,
00:04:47что, конечно, особенно сегодня, со всеми этими атаками на цепочки поставок, довольно интересно, иметь ограниченный набор зависимостей.
00:04:55Очевидно, если Adonis будет скомпрометирован, у вас всё равно будут проблемы, но это меньше дополнительных зависимостей, которые вам нужны.
00:05:03Привет, Daki, я заканчиваю твой известный курс по React.
00:05:07Что ты предлагаешь изучить после чистого TypeScript или React плюс TypeScript?
00:05:11Да, React плюс TypeScript — это хорошая идея.
00:05:12Next.js — хорошая идея.
00:05:14Или вы погрузитесь в React Native после изучения React, чтобы создавать мобильные приложения, если захотите.
00:05:20Так что это всё разумные следующие шаги, я думаю.
00:05:24Итак, без лишних слов, не читая весь этот текст, давайте приступим.
00:05:28Давайте выберем наш путь.
00:05:31Вы узнаете здесь.
00:05:33Я хочу начать, на самом деле.
00:05:36Теперь одно дело, три подхода.
00:05:40Adonis.js поддерживает три основных подхода к созданию вашего фронтенда.
00:05:44Окей, это звучит важно.
00:05:47Каждый подход представляет собой разный способ мышления о слое представления.
00:05:52Гипермедиа.
00:05:52Гипермедиа-приложения генерируют полные HTML-страницы на сервере и отправляют их в браузер.
00:05:57Вы строите свой интерфейс, используя шаблонизатор.
00:06:00И Adonis.js поставляется со своим шаблонизатором, это Edge.
00:06:05И добавляйте интерактивность, используя легкие библиотеки JavaScript, такие как Alpine.js.
00:06:10Или HTMX, если нужно.
00:06:12И я думаю, что хочу использовать этот подход, на самом деле.
00:06:16Вы могли бы, однако, также использовать Adonis с React в качестве фронтенда, используя Inertia.js,
00:06:25который, я думаю, из мира Laravel,
00:06:28который как бы является мостом между фронтенд одностраничным приложением
00:06:32и бэкендом фулстек-приложения.
00:06:38И, да, вы также можете просто создать REST API, конечно, просто бэкенд, если хотите.
00:06:46И тот же контроллер, три разных ответа.
00:06:49Окей, так что давайте посмотрим.
00:06:50Мы можем зарегистрировать маршрут с помощью роутера, который идет в комплекте с Adonis.
00:06:56И контроллер, так что это контроллер здесь.
00:07:02И там мы можем вызвать viewRender и отрендерить представление, которое мы определили ранее.
00:07:06И этот специальный синтаксис здесь, это по сути язык шаблонов Edge, который поставляется с Adonis.
00:07:16Альтернативой было бы использование Inertia, где у нас также есть наш контроллер.
00:07:20Но в контроллере мы вызываем render, всё еще на представлении, и мы можем передать некоторые props.
00:07:28Да, это props внутри него.
00:07:30И тогда у нас может быть наш JavaScript, наш код React здесь.
00:07:34И он будет, насколько я понимаю, отрендерен на сервере.
00:07:37И, по сути, нам не нужно получать данные в этом React-компоненте.
00:07:42Всё это будет обработано за нас.
00:07:44Так что это тоже хорошо.
00:07:45Но я думаю, что я, ну, мы увидим, что я буду использовать.
00:07:47Один из двух, очевидно, я хочу создать небольшое фулстек-приложение здесь.
00:07:50Но мы увидим.
00:07:51Я, вероятно, начну с шаблонизатора Edge и создам хорошее старое многостраничное приложение
00:07:57где мы рендерим HTML на стороне сервера.
00:07:59Потому что не всем приложениям нужен React на стороне клиента.
00:08:03Я думаю, это действительно важно понимать.
00:08:05Это зависит от того, что вы строите.
00:08:07И не каждому приложению нужен супер-реактивный, интерактивный фронтенд.
00:08:12Если вы создаете что-то вроде блога, например, вам, скорее всего, это не нужно.
00:08:16Но также для многих более сложных приложений вам это может не понадобиться.
00:08:20Давайте быстро прочитаю чат.
00:08:22Привет, Макс.
00:08:23Курс по разработке ИИ.
00:08:24Может быть, в какой-то момент, прямо сейчас всё меняется так быстро, что любой курс, который я бы
00:08:28выпустил по этому поводу, устарел бы практически в тот же момент, когда я его выпущу.
00:08:32Так что я этого не хочу.
00:08:32Так что не сегодня.
00:08:35Я лучше создам курсы по основам программного обеспечения и тому подобным вещам сначала.
00:08:39Но в какой-то момент я, конечно, хочу поделиться тем, как я работаю с ИИ.
00:08:44Но я хочу сделать это в тот момент, когда это не меняется каждую неделю, как сейчас.
00:08:48Привет, Макс.
00:08:48Я знаю, что Adonis поддерживается, я думаю, более десяти лет.
00:08:51Как ты думаешь, это бизнес-риск — делать на него ставку, учитывая его относительно нишевый рынок?
00:08:55Да, это действительно хороший вопрос.
00:08:57Я знаю, что его поддерживают очень долгое время.
00:09:01Я не знал, что это десятилетие.
00:09:02Но да, определенно долгое время.
00:09:05И я также не знаю, насколько велика команда Adonis.
00:09:09Я знаю, что он хорошо поддерживается прямо сейчас.
00:09:13Я вижу много активности в X со стороны ведущего разработчика, владельца проекта Adonis.
00:09:20Очевидно, всегда есть риск, связанный с проектом, который не используется всем миром, скажем так.
00:09:30С учетом сказанного, поскольку он поддерживается так долго, это доказывает преданность ведущего разработчика.
00:09:38Но да, очевидно, что у чего-то вроде Next.js, который поддерживается Vercel, будет очень вероятно, я бы сказал, более высокая гарантия долгой поддержки.
00:09:50Но никогда не знаешь наверняка.
00:09:52И у Adonis есть определенные преимущества, конечно, которых нет у Next.js.
00:09:57Но да, определенно обоснованное беспокойство.
00:10:00Приятно, что ты в эфире.
00:10:01Мне очень нравится твой подход к языкам программирования, фреймворкам, и Adonis выглядит довольно интересно на первый взгляд.
00:10:05Так что мне любопытно, что мы получим сегодня.
00:10:07Да, мне тоже любопытно.
00:10:08Спасибо, что присоединились.
00:10:09Должно быть весело.
00:10:10Какой инструмент вы используете для выделения областей?
00:10:12Это приложение под названием DemoPro.
00:10:15Это приложение, которое существует только для Mac.
00:10:17Я думаю, я купил его много-много лет назад.
00:10:21Оно отличное.
00:10:21Оно дает вам всё то, где вы можете рисовать на экране.
00:10:25Да.
00:10:27Я до сих пор не понимаю, почему его не приняло сообщество JavaScript.
00:10:30Я думаю, что фреймворки с жестким мнением — это отлично.
00:10:33Людям нравятся Svelte и Vue, так почему не Adonis?
00:10:35Да.
00:10:36Я всегда задавался этим вопросом.
00:10:37Я знаю, что я смотрел на Adonis, я не знаю, может, лет семь-восемь назад.
00:10:44И я задавался вопросом тогда, почему он не более популярен.
00:10:48И я лично никогда не находил времени, чтобы погрузиться глубже.
00:10:52И он никогда не был настолько популярным.
00:10:54Поэтому он никогда не всплывал как тема курса или что-то в этом роде.
00:10:59Но да, я не знаю.
00:11:00Я действительно не знаю, потому что он выглядит хорошо.
00:11:02Но я думаю, мы узнаем, насколько он хорош, по крайней мере, когда начнем.
00:11:07И поэтому, давайте начнем.
00:11:09Да.
00:11:10Нам нужен Node, конечно, создать новое приложение, npm create.
00:11:16Так что позвольте мне скопировать это.
00:11:19Я уже создал небольшую папку здесь.
00:11:21Я не буду использовать npm, но bun, потому что это быстрее и немного безопаснее.
00:11:25Могу ли я создать это в этой папке?
00:11:27Это работает?
00:11:29Да.
00:11:29Окей.
00:11:30Теперь я должен выбрать.
00:11:31Хочу ли я использовать Hypermedia приложение?
00:11:33Так, шаблонизатор, React, view приложение.
00:11:38Я выберу Hypermedia здесь.
00:11:39Он скачивает стартовый набор, устанавливает зависимости, мигрирует базу данных.
00:11:45Так что, кажется, он дает мне базовое стартовое приложение здесь.
00:11:53Команда не удалась.
00:11:55Node ace migration run.
00:11:58Хм.
00:11:59Это не очень хорошее начало.
00:12:01Это потому, что я использовал bun?
00:12:04Или потому что я использую...
00:12:05Может быть, это потому, что у меня последняя версия Node.js, Node 26.
00:12:12Может быть, есть проблема с этим, потому что я пытался запустить его с Node.
00:12:20Дайте посмотреть.
00:12:21Могу ли я запустить это так?
00:12:24Окей.
00:12:25У меня ошибка, новое исключение.
00:12:28Ох, мальчик.
00:12:29Есть такая тенденция, что когда я пробую что-то во время прямой трансляции, оно не работает.
00:12:35Не удается найти модуль startenv из Adonis bin console TS.
00:12:45Дайте проверить.
00:12:47Это Node?
00:12:48Давайте использовать более старую версию Node здесь.
00:13:01Нет.
00:13:02Теперь другая ошибка.
00:13:08Не удалось найти файл привязок.
00:13:14Так что, окей.
00:13:14Ой.
00:13:15Одно, что я попробую, так как, может быть, это была версия Node, я быстро очищу всё в этой папке.
00:13:24И я воссоздам его сейчас с помощью NPM и просто надеюсь, что меня сейчас не взломают через цепочку поставок.
00:13:34Я действительно параноидально отношусь к использованию NPM в эти дни.
00:13:38Я предпочитаю BUN или PNPM.
00:13:42Окей.
00:13:43Давайте попробуем снова.
00:13:44Давайте посмотрим, сработает ли это лучше.
00:13:52Я имею в виду, в этот момент не должно быть слишком много того, что я могу сделать неправильно.
00:14:11Команда не удалась.
00:14:12Это действительно не очень хорошее начало.
00:14:19Это что-то, что... есть ли у нас такая проблема здесь?
00:14:23Что-то, что известно?
00:14:27Не похоже.
00:14:36Окей.
00:14:37Давайте посмотрим.
00:14:38Одно, что мы можем попробовать, это дать это ИИ.
00:14:43И посмотреть, сможет ли он разобраться.
00:14:46Так что, я запущу Pi, моего любимого кодинг-агента на данный момент.
00:14:57Пытаюсь начать работу с Adonis в этом проекте.
00:15:02Запустил.
00:15:03Какая была команда?
00:15:04И NPM create это.
00:15:09Окей.
00:15:10NPM create.
00:15:13Adonis.js at latest dot.
00:15:17Он не сработал, когда пытался запустить миграции.
00:15:22Ручной запуск также не удался.
00:15:24Так что, давайте вставим этот журнал ошибок и посмотрим, что мы получим.
00:15:29Доброе утро.
00:15:30Или добрый вечер.
00:15:32Добрый день с моей стороны.
00:15:34Посмотрим, сможет ли ИИ помочь нам здесь.
00:15:38Если он сможет разобраться с этим сообщением об ошибке.
00:15:41Что такое Adonis.js?
00:15:42Adonis.js — это JavaScript-фреймворк.
00:15:44Полностековый фреймворк.
00:15:47Что-то вроде Laravel для JavaScript.
00:15:50Если вы знаете Laravel.
00:15:51В общем, это фреймворк “всё включено”.
00:15:53Не как Next.
00:15:54Не как Next.js или Tanstack Start, которые в основном про маршрутизацию и рендеринг на сервере.
00:15:59Вместо этого он идет с аутентификацией.
00:16:01У него есть собственный ORM.
00:16:03В этом-то и суть.
00:16:04Прямо сейчас я просто столкнулся с некоторыми проблемами при начальной настройке.
00:16:10О, понятно.
00:16:11Значит, нет.
00:16:14Хорошо.
00:16:15Понял.
00:16:16Это не Adonis.
00:16:18Вероятно.
00:16:19Но проблема, похоже, в том, что эта команда установки хотела запустить какой-то скрипт жизненного цикла.
00:16:28Какой-то скрипт, привязанный к зависимости.
00:16:31А у меня стоит “ignore scripts” на true из-за атак на цепочку поставок.
00:16:35И Bun, насколько я знаю, тоже не запускает их по умолчанию.
00:16:38Похоже, ему нужно было выполнить какой-то скрипт.
00:16:45Так что ИИ временно отключил это.
00:16:49Теперь запустил миграции.
00:16:54Хорошо.
00:16:57Будем надеяться, что теперь на этапе начальной настройки ничего не пропущено.
00:17:05Посмотрим.
00:17:07Потому что мы, конечно, можем попытаться запустить сервер разработки.
00:17:15Так что, давайте.
00:17:19Да, я не хочу использовать этот браузер здесь.
00:17:22Посмотрим.
00:17:24Окей.
00:17:25Так, что-то появилось на экране.
00:17:31Выглядит немного странно.
00:17:37Так и должно выглядеть?
00:17:41Хм.
00:17:43Окей.
00:17:45В общем.
00:17:50Итак, посмотрим.
00:17:51Я могу здесь зарегистрироваться.
00:18:05И теперь я вошел в систему.
00:18:07Я могу выйти.
00:18:08И все это встроено прямо из коробки.
00:18:12Классические проблемы всегда возникают тогда, когда их быть не должно.
00:18:15Да.
00:18:16Это действительно классика.
00:18:17Кажется, это уже третий раз, когда я пытаюсь погрузиться в технологию во время стрима.
00:18:22И всё просто ломается.
00:18:23Но, да.
00:18:23Сейчас работает.
00:18:25Кажется, сейчас всё работает без проблем.
00:18:31Не уверен насчет этой папки temp.
00:18:33Это где хранится моя продакшн-база данных?
00:18:36Или база для разработки?
00:18:37Схема.
00:18:38Пользователи.
00:18:39Да.
00:18:39Окей.
00:18:40Так что он использует SQLite, что мне нравится, потому что это легковесно и просто.
00:18:45И мы изучим, что здесь есть, через секунду.
00:18:48Udemy нужно добавить возможность подписываться на преподавателей, чтобы видеть, когда у них выходит новый контент.
00:18:53И не говорите мне.
00:18:54Я имею в виду, мы вместе с другими преподавателями так долго говорили Udemy, сколько крутых функций они могли бы добавить.
00:19:01Но, да.
00:19:02Они просто не хотят, полагаю.
00:19:05Мне нравится, как ты пытался разобраться с проблемой самостоятельно, прежде чем использовать ИИ.
00:19:08Я бы первым делом скопировал и вставил это в ИИ.
00:19:11Похоже, я обречен.
00:19:12Ну, как видишь, ИИ разобрался, когда я не смог.
00:19:15Но я также не хотел проходить через весь этот стек ошибок, потому что я не хочу, чтобы этот стрим был про отладку, а про Adonis.
00:19:25Поэтому, особенно когда дело доходит до разбора длинных сообщений об ошибках и рассуждения о них, ИИ действительно хорош.
00:19:31Я просто думаю, что есть смысл хотя бы бегло взглянуть на сообщение об ошибке самостоятельно, прежде чем отправлять его ИИ.
00:19:38Потому что, А, иногда это решается супер просто.
00:19:42Может быть, это просто занятый порт или что-то в этом роде.
00:19:45Не в этом случае, но в других проблемах.
00:19:47И, Б, никогда не бывает лишним иметь хоть какое-то представление о том, что происходит и какая часть ломается, и так далее.
00:19:58В любом случае, давайте посмотрим, что у нас здесь.
00:20:01В этом проекте, очевидно, есть файл package.json.
00:20:08Есть некоторые мэппинги, по сути, для файлов, из которых состоит этот проект.
00:20:14Затем мы получаем некоторые зависимости от Adonis.
00:20:19Что такое Vine?
00:20:24Библиотека валидации, хорошо.
00:20:25У нас есть библиотека валидации, better-sqlite3, edge.js — это язык шаблонов, как я понял.
00:20:34Что такое Luxon?
00:20:39Что это?
00:20:41Библиотека для работы с датами и временем.
00:20:44Хорошо, у нас есть это, и еще у нас есть, где тут assertions, тест-раннер, типы, Alpine.
00:20:54Alpine — это по сути JavaScript-библиотека для добавления легковесного клиентского кода, чтобы вам не приходилось писать ванильный JS, но при этом вам не нужна полноценная большая библиотека вроде React.
00:21:05Окей, Adonis RC TS выглядит как конфиг-файл, там экспериментальные флаги, команды, список ACE-команд для регистрации.
00:21:15Да, прошло много времени с тех пор, как я последний раз работал с Laravel.
00:21:20Я много занимался разработкой на Laravel в 2015, 2014 и 16, я думаю, и насколько я помню, у Laravel было много функций, как у Adonis, судя по всему, и он также позволял регистрировать собственные команды.
00:21:38Так что идея в том, что в Laravel, я думаю, это была команда artisan, а здесь это ACE-команда, которую вы выполняете через Node.
00:21:49Так что это команда или инструмент, предоставленный Adonis, и вы можете регистрировать свои собственные подкоманды, в основном, насколько я понимаю, которые, как я полагаю, вы регистрируете в... нет, это встроенные команды, а вы могли бы, по сути, импортировать сюда свои файлы.
00:22:05Так что мой файл TS, что-то вроде этого, вероятно, мог бы регистрировать ваши собственные команды, чтобы у вас были свои служебные команды.
00:22:15Провайдеры сервисов для импорта и регистрации, так что мое понимание здесь в том, что это касается внедрения зависимостей (DI) и регистрации различных сервисов, которые запускаются по мере запуска веб-сервера.
00:22:26Так что у нас здесь есть?
00:22:28Так что у нас здесь есть?
00:22:28У нас есть провайдер базы данных, провайдер авторизации, так что у нас есть разные провайдеры для разных функций, так сказать.
00:22:34Preload, окей, по сути, это наш конфигурационный файл, понял.
00:22:40Что еще у нас есть?
00:22:41У нас есть файл .env, где мы настраиваем порт и так далее, уровень логирования, есть ключ приложения здесь для...
00:22:50Я не знаю, для чего это используется, для авторизации, для хеширования паролей или чего-то еще, не знаю.
00:23:01Драйвер сессии cookie, хорошо, так что мы используем куки для аутентификации, вот наша база данных здесь, это должно быть...
00:23:12Gitignore.
00:23:14Temp, да.
00:23:16Tests, наши юнит-тесты настроены здесь.
00:23:23Resources, да, это просто как в Laravel, я думаю.
00:23:27В Laravel у нас также была папка resources с клиентскими ресурсами, так что здесь у нас клиентский CSS, клиентский JavaScript, использующий Alpine, как я и упоминал.
00:23:40И views — это по сути фронтенд-страницы, или шаблоны, которые будут отрисовываться в страницы, и, похоже, все компоненты.
00:23:49Но я пока не знаю, как работает эта система шаблонов.
00:23:53Сейчас я быстро посмотрю, смогу ли я установить какое-нибудь расширение и, надеюсь, не подцепить атаку на цепочку поставок для этого шаблонизатора Edge.
00:24:02Поддержка шаблонов Edge, вот она, официальная: подсветка синтаксиса шаблонов Edge от Adonis.js.
00:24:09Давайте установим.
00:24:12О господи, только не взломайте меня.
00:24:16Окей, выглядит лучше.
00:24:18Так что теперь у нас есть подсветка синтаксиса.
00:24:20В общем, идея шаблонизатора... В старые добрые времена было довольно распространено использовать языки шаблонов, в том числе в других JavaScript-фреймворках.
00:24:32И идея на самом деле в том, что вы рендерите HTML-страницы на сервере, а затем готовый HTML-код отправляется клиенту.
00:24:39Но чтобы сделать это немного удобнее и динамичнее, вы составляете HTML-файл из разных шаблонов и имеете в них плейсхолдеры, которые могут быть заменены динамическими значениями.
00:24:51И что у нас здесь, например, как кажется, это то, что мы говорим: окей, эта домашняя страница, так что мы в папке pages, эта домашняя страница должна быть основана на layout.
00:25:02И я предположил бы, что можно определить разные лейауты, но если вы ничего здесь не указываете, используется лейаут по умолчанию, который где-то зарегистрирован.
00:25:09И затем эта часть внедряется в этот лейаут.
00:25:12Так что в этом лейауте у нас, вероятно, есть плейсхолдеры.
00:25:14Посмотрим, где определен лейаут, components layout здесь.
00:25:20Так что это файл лейаута.
00:25:22Так что здесь мы видим общий HTML-скелет.
00:25:24Мы также видим, что в body у нас есть этот main slot.
00:25:29Похоже, это синтаксис языка Edge шаблонов для определения слота, куда рендерится актуальный контент страницы.
00:25:39Опять же, я не знаю, как работает этот язык.
00:25:42Я просто пытаюсь понять его, читая код.
00:25:44Так что, похоже, может это имя, которое мы можем назначить.
00:25:47Может это зарезервированное имя.
00:25:49Не знаю.
00:25:50И это асинхронно.
00:25:51Это интересно.
00:25:52Мы ожидаем.
00:25:53Так что мы закончим рендеринг лейаута только после того, как это будет отрендерено здесь.
00:25:57Slots main.
00:25:59Так что это, по сути, зарезервированное имя.
00:26:01И помимо этого, у нас есть концепция partials, которую я также знаю по Laravel, что тоже довольно типично, чтобы у вас был не просто лейаут со слотом для основного контента, но и другие компоненты, которые вы можете привнести в лейаут, а потенциально и в другие страницы.
00:26:18Так что здесь у нас partial для заголовка, для flash-оповещений, для небольших дополнительных сообщений, которые вы хотите показать на экране, может быть.
00:26:26И, например, этот partial header можно найти в папке partials/header.
00:26:33И здесь у нас теперь заголовок.
00:26:35И там у нас больше синтаксиса шаблонизатора для рендеринга ссылки.
00:26:40И ссылки рендерятся так, потому что они тоже динамические.
00:26:43Они зависят от маршрутов, которые вы зарегистрировали, если это внутренние ссылки.
00:26:47Так что здесь мы настраиваем ссылку на домашний маршрут с текстом “home”.
00:26:52И мы можем видеть это.
00:26:54Где мы можем это видеть?
00:26:55Можем ли мы видеть это внизу?
00:26:58Или, о, нет.
00:26:59Это вот это.
00:26:59Это здесь SVG.
00:27:01Так что это, по сути, это SVG, я полагаю.
00:27:04У него есть fallback-имя “home”.
00:27:06И если мы кликнем по нему, нас перенесет на домашний маршрут.
00:27:13Хорошо, тогда у нас здесь есть условный рендеринг, в зависимости от того, есть ли у нас залогиненный пользователь или нет.
00:27:19Логично.
00:27:20Это все еще в заголовке.
00:27:23Окей.
00:27:23И затем здесь, например, это @vite.
00:27:26Судя по всему, мы используем Vite для фронтенд-ресурсов, для сборки и управления CSS- и JavaScript-файлами фронтенда.
00:27:35И я полагаю, что мы внедряем сюда оптимизированные и собранные файлы app.js и app.css.
00:27:45Или, если точнее, мы находим их в папке resources в подпапках JS и CSS.
00:27:49Так что это именно тот самый JavaScript-файл с CSS.
00:27:53Так что я не знаю, обрабатываются ли они даже.
00:27:57Понял.
00:27:58И сервер Vite запускается автоматически, когда мы запускаем основной dev-сервер, я полагаю.
00:28:05Так что, окей.
00:28:06Логично.
00:28:06Я не всё здесь понимаю.
00:28:08Этот стек здесь — это, наверное, какая-то отладочная штука.
00:28:11Не знаю.
00:28:12И еще у нас здесь есть компоненты.
00:28:15И, да.
00:28:16Мне придется разобраться в этом.
00:28:17Что именно здесь происходит.
00:28:19Но мы сделаем это в свое время.
00:28:21Давайте вернусь к чату.
00:28:22Несколько вопросов.
00:28:24LLM-модели Макса становятся дороже в запуске, использовании и больше не субсидируются.
00:28:28Станут ли open-source или self-hosted модели важнее?
00:28:31И, как результат, стоит ли разработчикам учить DevOps для этого сдвига?
00:28:35Так что я думаю, что открытые модели станут важнее в будущем в целом.
00:28:42Но, конечно, если вы хотите запускать их самостоятельно, это тоже будет стоить денег.
00:28:45Потому что либо вам нужна довольно мощная локальная машина.
00:28:48Типа Mac Studio за 10 тысяч или что-то в этом роде.
00:28:52Или вам придется снова арендовать её.
00:28:53Так что это всегда будет стоить каких-то денег.
00:28:56Но, конечно, в зависимости от того, насколько дорогими станут передовые модели, открытые модели могут стать интересной альтернативой.
00:29:03Существует не так много супер способных открытых моделей, в зависимости от того, что вы пытаетесь сделать.
00:29:10Но я уверен, мы к этому придем.
00:29:12Я не думаю, что вам стоит учить DevOps для этого, однако.
00:29:16Вам стоит учить это, если это в целом интересно вам.
00:29:19Но деплой и запуск своей собственной открытой модели — это то, что вы можете сделать, если у вас есть оборудование,
00:29:25или если вы арендуете VPS, сделать один раз.
00:29:28Но вам просто нужно научиться сделать это правильно один раз.
00:29:32Вам не нужно в целом учить много DevOps, я бы сказал.
00:29:36И, привет, спасибо, что проходишь мой курс по Flutter.
00:29:41Спасибо за приятное упоминание, Don Solid.
00:29:47И почему мне стоит использовать этот инструмент, а не напрямую обращаться к ИИ-сервису?
00:29:51Я не уверен, о каком инструменте речь.
00:29:54Есть ли шанс, что вы опубликуете свои новые курсы на Udemy?
00:29:57Вы всё ещё делаете курсы для Udemy?
00:30:01Иногда делаем.
00:30:02Но Udemy сейчас не лучшая площадка для новых разработок.
00:30:07Так что посмотрим, как всё сложится после поглощения Coursera и так далее.
00:30:14А насчёт политики безопасности контента — я полагаю, вы можете перейти к макету,
00:30:22и просто добавить всё, что нужно, в секцию head здесь.
00:30:25В конечном итоге это просто HTML, так что можете добавить это там.
00:30:32Так что это должно сработать.
00:30:34Но я, конечно, только начинаю знакомство с Adonis.
00:30:42Хорошо, с этим разобрались.
00:30:44Давайте пропустим, или, пока что, оставим фронтенд, ресурсы.
00:30:48Давайте взглянем на папку start.
00:30:50Это, должно быть, серверная часть, потому что мы исследовали... нет, мы не всё исследовали.
00:30:56Там есть ещё.
00:30:57У нас есть база данных, которая содержит миграции.
00:31:00Идея здесь, как и во многих других фреймворках, заключается в том, что мы определяем таблицы базы данных
00:31:08в файлах миграций, которые, судя по всему, имеют такой формат.
00:31:12И я полагаю, что существуют также команды, которые мы можем запустить для автоматического создания этих файлов миграций.
00:31:17И затем мы запускаем эти миграции, чтобы применить их к базе данных, чтобы, по сути, спроектировать наши таблицы и их схемы.
00:31:24Итак, у нас есть это, schema TS.
00:31:28Хорошо, значит, мы настраиваем схему, таблицу базы данных как класс, по сути, как кажется.
00:31:33А затем мы, вероятно, создаём миграцию программно с помощью определённой команды.
00:31:40Config, о, здесь много чего можно настроить.
00:31:43Хорошо, значит, там мы можем настроить кучу всего.
00:31:50Хорошо, доберёмся до этого, когда понадобится, я полагаю.
00:31:53Bin, server TS, HTTP-сервер, точка входа.
00:31:57Файл server TS — это точка входа для запуска HTTP-сервера Adonis.js.
00:32:02Вы можете либо запустить этот файл напрямую, либо использовать команду serve.
00:32:05Так что это было выполнено для нас, когда мы запустили сервер разработки с помощью команды serve здесь.
00:32:13Что мы там делаем?
00:32:18Импортер, инициатор.
00:32:23По сути, загрузка сервера, начало прослушивания порта.
00:32:27Регистрация маршрута где-то, точно.
00:32:34Что за консоль — это точка входа для загрузки командной строки фреймворка Adonis.js.
00:32:38То есть это на случай, если мы регистрируем пользовательские команды или выполняем какие-то встроенные команды, я полагаю, с помощью команды ace.
00:32:45И приложение, хорошо.
00:32:46Итак, здесь мы регистрируем стартовые вещи.
00:32:49А start кажется интересным.
00:32:51Так что в start у нас есть файл routes TS, например.
00:32:54И здесь мы явно регистрируем маршруты нашего приложения.
00:33:00Типа вот так для слэша, ничего.
00:33:02То есть домен слэш ничего.
00:33:04Мы отображаем домашнюю страницу.
00:33:06Так что здесь мы ссылаемся на пути в нашей папке resources views.
00:33:12То есть в resources views.
00:33:15Так что если у нас есть типа render pages home, это идёт в папку pages здесь.
00:33:20И затем там он отрисовывает home.
00:33:23Это, по сути, то, что здесь происходит.
00:33:28И мы можем группировать маршруты.
00:33:31Зачем нам группировать?
00:33:33Чтобы применить общее связующее ПО, верно?
00:33:35Гостевое связующее ПО (guest middleware).
00:33:38Что бы оно ни делало.
00:33:40И затем мы получаем здесь маршруты регистрации и входа.
00:33:44Да, вероятно, это некое связующее ПО, что только неаутентифицированные пользователи могут достичь этих маршрутов.
00:33:49А с другой стороны, мы получаем связующее ПО аутентификации, чтобы защитить маршруты, которые должны быть доступны только аутентифицированным пользователям.
00:33:56Например, маршрут выхода, который имеет смысл, только если мы, ну, выходим из системы.
00:34:00И тогда каждый маршрут либо регистрируется вот так, где мы напрямую что-то отображаем, либо — и я знаю это из Laravel тоже, вероятно, более распространено или более в духе официальной философии — поставить вот так, это подключить контроллер и определённый метод контроллера к маршруту.
00:34:21Так что здесь для регистрации у нас есть два маршрута, один get и один post маршрут, и это в том же файле контроллера, но мы нацеливаемся на разные контроллеры, на создание и на хранение контроллера.
00:34:35Если мы взглянем на это, наши контроллеры в файле controllers.ts здесь, которые находятся в adonis.js server, dot adonis.js server.
00:34:47Да, но это, это создано динамически, разве нет?
00:34:51Мы создавали это?
00:34:53Разве нет?
00:34:55Нет, мы регистрируем наши контроллеры здесь.
00:34:59Я полагаю, это генерируется динамически.
00:35:01Так что, здесь, новый контроллер учётной записи.
00:35:04У нас есть наш класс, контроллер новой учётной записи.
00:35:08И затем в нём у нас есть метод создания и метод хранения.
00:35:12И они в конечном итоге отвечают за эти имена.
00:35:15И опять же, мы увидим, но я полагаю, что это как-то создаётся динамически или автоматически.
00:35:21И затем в create, который предназначен для get-маршрута, мы просто отображаем другое представление.
00:35:25Так что, конечно, в теории, мы могли бы также не использовать это, но вместо этого мы могли бы, я полагаю, также сделать get.
00:35:41Да, мы могли бы... нет, мы не можем... разве мы не можем напрямую здесь отобразить?
00:35:46Нам обязательно использовать контроллер?
00:35:50Похоже, что да, хорошо.
00:35:51Но в конечном итоге, мы отображаем его так же, как делали это здесь.
00:35:56И для post-маршрута здесь мы проверяем ввод пользователя с помощью встроенного валидатора.
00:36:04А затем мы создаём новый экземпляр пользователя, используя нашу модель пользователя, к которой я вернусь.
00:36:11И затем мы аутентифицируем этого пользователя для веба.
00:36:15То есть аутентификация на основе сессий, на основе файлов cookie, я полагаю.
00:36:18И затем мы перенаправляем обратно на домашний маршрут.
00:36:21Так что давайте посмотрим.
00:36:24У нас есть папка моделей.
00:36:26В ней определена модель пользователя.
00:36:28И я полагаю, что... я упоминал ранее, что у нас есть эти таблицы базы данных, у нас есть эти схемы.
00:36:40И, вероятно, мы просто определяем модель, а остальное генерируется автоматически, но мы это увидим.
00:36:47Так что в конечном итоге здесь мы определяем, что хотим иметь пользователя или пользователей в нашем приложении.
00:36:53И затем мы расширяем некоторые вещи, которые приходят из Adonis.
00:36:57И затем у нас здесь есть небольшой геттер, инициалы.
00:37:03Хорошо, это просто вспомогательная функция для получения полного имени пользователя путём объединения имени и фамилии.
00:37:10Просто чтобы показать, как можно, по сути, создавать вычисляемые значения, подобные этому.
00:37:15Хорошо, понял.
00:37:17Валидаторы для пользователя.
00:37:19Небольшой файл валидации, где мы используем эту библиотеку wine, которую я не знал раньше, для того, чтобы, по сути, обеспечить получение непустого адреса электронной почты с определённой максимальной длиной.
00:37:31Прошу прощения.
00:37:36И затем мы, кажется, можем создавать определённые повторно используемые валидаторы, которые мы можем использовать во всех местах, где мы хотим проверять при регистрации, где мы затем принудительно устанавливаем определённые значения.
00:37:49Хорошо, связующее ПО, связующее ПО аутентификации — это просто класс с методом handle, где мы что-то проверяем и возвращаем next, если хотим предоставить доступ к любому маршруту, на который направлялся пользователь.
00:38:07И я полагаю, что это вызывает ошибку, если аутентификация не удалась, чтобы предотвратить это при следующей навигации.
00:38:14Гостевое связующее ПО, я полагаю, делает обратное.
00:38:21Да, мы проверяем, аутентифицирован ли пользователь, и затем перенаправляем, если это так.
00:38:28И мы предоставляем доступ только туда, куда они направлялись, если они не были аутентифицированы.
00:38:32Хорошо.
00:38:33Исключения позволяют нам определять наши собственные ошибки, наши собственные исключения.
00:38:38Хорошо.
00:38:40Хорошо.
00:38:42Итак.
00:38:45Какие новые курсы вы планируете выпустить в ближайшем будущем?
00:38:52Может быть, что-то по BUN.
00:38:55Я всё ещё выясняю, доволен ли я этим курсом.
00:38:58Так что я уже записал что-то, но хочу проверить, доволен ли я качеством и так далее, и доволен ли я направлением.
00:39:06Некоторые основы программной инженерии, проектирование систем — это курсы, которые я хотел бы создать в этом году.
00:39:12А что касается агентного ИИ, я знаю, что это, вероятно, хорошо продавалось бы, но я ответил на это ранее.
00:39:20Проблема в том, что я хотел бы создать курс, где я делюсь тем, как я занимаюсь агентной инженерией и работаю с ИИ.
00:39:26Проблема просто в том, что всё меняется слишком часто.
00:39:30Так что я не верю, что это будет очень полезно прямо сейчас.
00:39:33Как только у меня появится ощущение, что это немного более стабильно, я бы хотел создать такой курс по агентной инженерии или инженерии ИИ, или как вы хотите это назвать.
00:39:42Это выглядит как puck.js.
00:39:44Да.
00:39:45Зачем кому-то использовать его в 2026 году?
00:39:48Я не думаю, что кто-то будет использовать Vue.
00:39:51Всё дело в SPA.
00:39:53Я здесь не согласен.
00:39:56Я думаю, мы так привыкли к одностраничным приложениям и React повсюду.
00:40:01И React великолепен.
00:40:02И я имею в виду, безусловно, также есть правда в том, что ИИ любит React.
00:40:07А Adonis в целом довольно нишевый.
00:40:10Но я думаю, это неверное предположение, что нам нужно использовать React повсюду.
00:40:17Возможности просто отображать шаблоны на сервере часто достаточно.
00:40:23Часто достаточно.
00:40:24И часто добавление React может просто добавить больше сложности, больший размер бандла.
00:40:30Подумайте о некоторых уязвимостях безопасности, которые у нас были за последние недели.
00:40:35Так что есть смысл не вводить то, что вам не нужно, просто потому, что вы к этому привыкли.
00:40:41Мы так привыкли использовать React для всего, что просто принимаем это как должное, как стандартный вариант, который мы должны использовать.
00:40:47И я не думаю, что это так.
00:40:49Нет, я согласен.
00:40:50Это определённо выглядит немного устаревшим.
00:40:53И как я уже сказал, я писал свои страницы вот так много, много лет назад.
00:41:00Я всё ещё не сказал бы, что это неправильно сегодня, однако.
00:41:03Это определённо необычно и не то, что кажется родным или что имело бы много смысла.
00:41:12Но я бы сказал, что это может иметь смысл.
00:41:14Теперь, при всём при этом, как я уже сказал ранее, Adonis поддерживает различные способы отображения представлений.
00:41:23Он поддерживает React в качестве фронтенда и затем использует Inertia.js как мост.
00:41:29Так что вы абсолютно точно можете создавать полнофункциональные приложения Adonis.js без этого подхода на основе представлений.
00:41:38Но я хотел проверить это сначала, потому что хотел посмотреть, как это выглядит.
00:41:43Типа выглядит как Hano.
00:41:45Да, я думаю, Hano немного... намного стройнее, верно?
00:41:48Так что в Hano нет всех этих функций, таких как аутентификация, ORM и так далее, встроенных в него.
00:41:56Как тебе Adonis.js?
00:42:00Я нахожу его интересным, но я совсем не использовал его раньше.
00:42:03Так что я только исследую его сегодня.
00:42:05И я только начал с ним работать.
00:42:07Мне нравится идея иметь всё включённым в один фреймворк, особенно сейчас, в дни,
00:42:13всех этих атак на цепочки поставок.
00:42:16И я думаю, в экосистеме JavaScript мы склонны тянуться к чрезмерно сложным решениям.
00:42:21И мы сшиваем вместе десятки библиотек, что также, помимо атак на цепочки поставок,
00:42:26имеет проблему, что не все эти библиотеки всегда хорошо поддерживаются.
00:42:31Так что иметь просто один фреймворк, где есть всё необходимое, определённо имеет свои достоинства, я бы сказал.
00:42:39Как вы рекомендуете нынешним студентам компьютерных наук, у которых есть базовые знания, учиться программировать?
00:42:44Какой следующий шаг?
00:42:45Создать проект или исследовать ИИ?
00:42:46Я бы использовал ИИ для обучения.
00:42:48Я бы создавал проекты также с помощью ИИ, но я бы не использовал только ИИ, потому что, очевидно,
00:42:53вы ничему не учитесь от этого.
00:42:54Я бы попытался изучить основы программной инженерии.
00:42:57Я бы определённо попытался написать немного кода вручную здесь и там.
00:43:01Я бы определённо просматривал и действительно понимал весь код, который может сгенерировать ИИ.
00:43:05Я бы мог критически поставить его под сомнение.
00:43:07Может быть, также использовать ИИ для обсуждения кода.
00:43:10Но буду честен, я тоже всё ещё пытаюсь выяснить, как лучше всего учить и, конечно,
00:43:15также изучать вещи с ИИ в наши дни.
00:43:20Как вы создаёте проект сегодня, чтобы учиться, если я спрашиваю ИИ?
00:43:27Да.
00:43:27Так что я бы действительно использовал ИИ как спарринг-партнёра, по сути.
00:43:32Хорошо.
00:43:32Итак, давайте посмотрим.
00:43:34Сейчас я также хочу увидеть альтернативы, раз мы только что говорили об этом.
00:43:38И затем мы также перейдём к редактированию кода.
00:43:40Но я хочу увидеть альтернативу.
00:43:42Что, если я использовал.
00:43:47Позвольте мне воссоздать это.
00:43:49Хочу начать с нуля.
00:43:51Позвольте мне воссоздать это.
00:43:52Остановить сервер.
00:43:53И использовать альтернативный подход здесь с React Kit.
00:44:01Теперь он, вероятно, снова упадёт.
00:44:08Так что позвольте мне быстро проверить.
00:44:15Какую команду он выполнил, чтобы это заработало?
00:44:19Постоянный.
00:44:20Я не хочу постоянный.
00:44:27Так что это здесь, вероятно, сделает это.
00:44:32Посмотрим.
00:44:36Посмотрим.
00:44:37Ой.
00:44:38Я не хотел этого делать.
00:44:39Одной точки достаточно.
00:44:42Окей.
00:44:44Посмотрим, заработает ли это.
00:44:55«Шварцмюллеринг» ваших штанов.
00:44:57Не уверен, хорошо это или плохо.
00:45:09Разработал ли я свой курс по Flutter с нуля?
00:45:11Да.
00:45:12Вся моя работа.
00:45:14Итак, теперь давайте запустим его снова.
00:45:21Посмотрим, выглядит ли он так же.
00:45:24Да.
00:45:25То же приложение.
00:45:26Но теперь, конечно, структура файлов должна быть другой.
00:45:29Давайте посмотрим.
00:45:32Папка app.
00:45:36Теперь у меня есть трансформер.
00:45:38Но, полагаю, это просто какие-то бэкенд-штуки.
00:45:42Нет.
00:45:42Это для передачи данных с сервера на клиент, я думаю.
00:45:46Итак, к фронтенду, давайте посмотрим.
00:45:48Bin, config, database, inertia.
00:45:53Окей.
00:45:53Inertia — это теперь папка фронтенда, я полагаю.
00:45:56CSS.
00:45:57Да.
00:45:57Окей.
00:45:58Итак, что у нас здесь есть?
00:45:59Есть файл app.tsx.
00:46:11Понятия не имею, что это, но полагаю, что он нужен для гидратации фронтенда и соединения его с бэкендом.
00:46:18Create inertia app.
00:46:20Устанавливает заголовок страницы, как кажется.
00:46:22App.
00:46:23Окей.
00:46:24Где находится файл конфигурации скриптов, который показывает мне ошибку, но это просто потому, что он устарел.
00:46:29Это нормально.
00:46:32Server-side rendering TSX.
00:46:34Итак, это точка входа для серверного рендеринга, клиентская точка входа.
00:46:39Окей.
00:46:39Я понятия не имею, как работает Inertia и что это за штука «два часа».
00:46:46У меня здесь домашняя страница.
00:46:47Так что это теперь обычный React-компонент.
00:46:51Ничего особенного.
00:46:52У нас есть лейаут или что-то подобное?
00:46:53Да, у нас есть лейаут.
00:46:54Default TSX.
00:46:55Где это настроено?
00:46:56Это настроено в app?
00:46:59Resolve page component.
00:47:00Искать в папке pages.
00:47:03Где layout, layout, layout, layout.
00:47:05Layout импортирован.
00:47:07Окей.
00:47:08Вот так это работает.
00:47:10У нас здесь наш лейаут.
00:47:12А потом получили дефолтный лейаут.
00:47:16Окей.
00:47:16Итак, у нас, о-о, use effect.
00:47:19Это запрещено.
00:47:24Окей.
00:47:25Да.
00:47:26Так что это действительно просто React.
00:47:27Как мы знаем, компонент link приходит из Inertia.
00:47:30Или из Adonis.js и его пакета Inertia.
00:47:35Окей.
00:47:37И насколько я понимаю, давайте посмотрим.
00:47:47Да.
00:47:47Children — это очевидно для...
00:47:51Окей.
00:47:52Окей.
00:47:53Окей.
00:47:54Интересно.
00:47:54Children — это, конечно, как всегда в React, компонент между тегами.
00:48:05Но у children также есть объект props со свойством user.
00:48:13И я полагаю, что оно где-то заполняется в наших контроллерах.
00:48:20Сначала, новая сессия, новый контроллер аккаунта регистрации или inertia render.
00:48:29Но там мы не передаем никаких пропсов.
00:48:32Контроллер сессии.
00:48:35Где это заполняется?
00:48:36Потому что у нас здесь есть эта штука с трансформером, которая, как я думал, предназначена для преобразования данных с сервера на клиент.
00:48:46Я не уверен.
00:48:50Return this pick, this resource, что угодно.
00:48:56Может, это тоже просто для получения данных из базы данных.
00:48:59Я не уверен.
00:49:01Окей.
00:49:02Итак, у нас есть эта настройка.
00:49:03Давайте продолжим с официальным руководством.
00:49:05Мне просто очень нравится самому погружаться в кодовую базу.
00:49:08А потом взглянуть на него, чтобы попытаться понять, прежде чем следовать руководству.
00:49:12Потому что я чувствую, что узнаю немного больше, делая это так.
00:49:16Да и кто вообще читает код в наши дни, верно?
00:49:18Так почему бы не использовать стрим, чтобы сделать это?
00:49:22Просто шучу.
00:49:23Я читаю код.
00:49:26Структура папок.
00:49:28Окей.
00:49:28Я только что изучил структуру папок.
00:49:31Папка app.
00:49:32Директория app организует код для доменной логики вашего приложения.
00:49:36Например, контроллеры, модели, почта.
00:49:39Так что да, как и в Laravel, он также помогает с отправкой почты, что, конечно, может быть супер удобно.
00:49:44Директория bin содержит файлы точек входа, используемые для запуска вашего приложения Adonis.js, console, server, TS.
00:49:50Обычно вам не нужно изменять эти файлы, если вы не хотите настроить загрузку приложения.
00:49:56Окей.
00:49:56Config: все файлы конфигурации приложения и сторонних библиотек живут внутри директории config.
00:50:01Вы также можете хранить конфигурацию, локальную для вашего приложения, внутри этой директории.
00:50:05Да, так что в папке config мы уже видели, есть вещи типа, не знаю, базы данных, которую мы используем, SQLite.
00:50:13Я полагаю, вы могли бы также подключиться к базе данных Postgres или что-то вроде того.
00:50:20Мы можем выбрать клиент.
00:50:21Так что, может быть, мы могли бы использовать что-то вроде клиента Buns SQLite здесь.
00:50:24Я не знаю.
00:50:25Определите путь к базе данных, временный путь.
00:50:28Итак, в этой папке temp здесь, миграции, что еще у нас есть?
00:50:34Config, inertia, серверный рендеринг, переключение режима серверного рендеринга.
00:50:39Да, я хочу серверный рендеринг, так что давайте включим это в true.
00:50:47Логгер, да.
00:50:48Так что это имеет смысл.
00:50:50Я просто быстро хочу проверить.
00:50:52Если я установлю это в false, моим предположением будет, что если я взгляну на исходный код страницы здесь, то у меня будет div app с некоторыми данными, которые передаются ему.
00:51:06Да, но основной HTML-контент отсутствует, потому что он отрисовывается на клиенте.
00:51:10Мы импортируем некоторые скрипты, которые затем выполняют клиентский рендеринг.
00:51:15Это не очень хорошо для поисковой оптимизации.
00:51:18Так что, если я установлю это в true, теперь мы видим, что там гораздо больше всего, верно?
00:51:26Там есть фактический, весь встроенный код, так что немного сложно читать, но фактический HTML-контент там есть.
00:51:31Так что я оставлю это установленным в true.
00:51:34Окей, база данных.
00:51:35Директория database хранит артефакты, относящиеся к уровню базы данных.
00:51:39По умолчанию он работает с Lucid ORM, то есть собственным ORM.
00:51:43И идея ORM заключается в том, что вы выражаете свои таблицы базы данных по существу как модели, как классы, можно сказать, в вашем коде.
00:51:51А затем базовые схемы и миграции генерируются для вас.
00:51:57И да, это первый раз, когда я изучаю этот фреймворк, поэтому я просто пытаюсь понять, как все это работает прямо сейчас.
00:52:03Переключение баз данных не требует реорганизации этой папки, миграции, версии, изменения схем, сидеры, если вы хотите иметь начальные данные, например, некоторых начальных администраторов или что-то подобное.
00:52:15Окей, провайдеры.
00:52:16Директория providers используется для хранения сервис-провайдеров, используемых вашим приложением.
00:52:20Что такое сервис-провайдеры?
00:52:22Сервис-провайдеры.
00:52:22Это руководство охватывает сервис-провайдеров.
00:52:24Ну, я, наверное, не буду изучать их полностью.
00:52:27Сервис-провайдеры — это JavaScript-классы с хуками жизненного цикла, которые выполняются в определенные моменты во время запуска и завершения работы приложения.
00:52:35Это позволяет вам регистрировать привязки к контейнеру инверсии управления, расширять классы фреймворка с помощью макросов, выполнять инициализацию в точные моменты, очищать ресурсы во время завершения работы.
00:52:53Так что это где у нас есть некоторые встроенные провайдеры.
00:52:58Где это?
00:53:02Я видел это раньше.
00:53:04Где встроенные провайдеры?
00:53:09Providers.
00:53:09Здесь API provider.
00:53:12Пользовательский сериализатор для ответов API.
00:53:17Окей, значит, здесь у нас есть провайдер для сериализации данных, как кажется.
00:53:22И я бы предположил, что есть больше встроенных провайдеров, которые помогают с авторизацией, так что они регистрируют кучу дефолтных middleware или что-то подобное.
00:53:30Было бы моим предположением.
00:53:33Давайте не будем сохранять это.
00:53:35Окей, public, директория public содержит необработанные статические активы.
00:53:39Я что, пропустил эту папку?
00:53:40Public.
00:53:46У меня нет папки public.
00:53:48Но полагаю, у меня тогда нет никаких публичных активов.
00:53:51Я мог бы, вероятно, добавить папку public, чтобы иметь необработанные активы, которые не будут оптимизированы.
00:54:05Я вижу почти нет вакансий в Adonis.
00:54:07Тогда зачем изучать такие вещи, которые не востребованы?
00:54:10Просто ради забавы?
00:54:10Йо, если вы, конечно, ищете работу, то Adonis.js...
00:54:15О, это такой сложный вопрос.
00:54:17Я имею в виду, да, Adonis.js не поможет вам, если вы просто ищете работу.
00:54:22Но, во-первых, изучение альтернатив всегда расширяет кругозор.
00:54:27Вы можете узнать о новых концепциях здесь, которые применимы к другим приложениям с другими технологическими стеками.
00:54:33Ради забавы — это очень веская причина.
00:54:36И, конечно, вы можете, если вы не ищете работу, если вы хотите, например, построить свой собственный SaaS, свой собственный бизнес, что угодно,
00:54:48то, конечно, это может быть веским вариантом.
00:54:52Если вы ищете работу, в зависимости от того, где вы находитесь, конечно, это может быть очень нишево.
00:54:58И, честно говоря, это настолько нишево, что будет очень трудно найти работу.
00:55:01Но, конечно, у вас было бы немного конкуренции, если бы вы находились в области, где есть какая-то работа для этого.
00:55:07Но это очень теоретически, конечно.
00:55:08Но да, для меня это просто забава сейчас.
00:55:10Я просто хочу изучить это, потому что я читал об этом, типа, уже восемь лет назад.
00:55:15И я наконец хочу понять, как это работает.
00:55:19Директория resources хранит шаблоны Edge и нескомпилированные фронтенд-активы, такие как CSS и файлы JavaScript, в приложении Inertia.
00:55:30Есть ли у меня ресурсы?
00:55:32Есть.
00:55:33Inertia layout.
00:55:35О.
00:55:35Так что это как скелет HTML, в который отрисовывается это приложение React.
00:55:41Так что мы могли бы настроить нашу политику безопасности контента здесь.
00:55:44Мы могли бы привнести сюда некоторые статические активы, я полагаю.
00:55:48Зарегистрировать некоторые метаданные в дополнение к тому, что у нас уже есть.
00:55:51Окей.
00:55:52Inertia: директория inertia существует только в проектах, использующих стартовый набор Inertia.
00:55:56Имеет смысл.
00:55:57Она представляет собой субоприложение, содержащее исходный код фронтенда.
00:56:01Вы вольны создавать дополнительные папки, такие как components, layouts, utils для организации.
00:56:06Так что по сути вы строите свой view или свое React-приложение там.
00:56:09Четкое разделение между фронтендом и бэкендом.
00:56:11Adonis.js поддерживает четкую границу между бэкендом и фронтендом.
00:56:14Вы никогда не должны импортировать бэкенд-код в ваше фронтенд-приложение, чтобы ничего там не раскрыть или чтобы оно не упало, потому что, очевидно, бэкенд-API или серверные Node.js API не будут работать на клиенте в браузере.
00:56:30На практике ваш фронтенд общается с бэкендом через HTTP-запросы и получает простые данные JSON.
00:56:35Adonis.js поощряет вас моделировать эту реальность явно.
00:56:39Данные выбираются и трансформируются через ответы API.
00:56:43Интересно, это любопытно, как именно мы общаемся здесь, используя Inertia?
00:56:49Так что, скажем, мы входим в систему.
00:56:52Так что у нас здесь есть форма.
00:56:54Да.
00:56:54И это интересно.
00:56:56Это компонент, приходящий из фреймворка Adonis.js.
00:57:01Оно принимает маршрут, и, я полагаю, мы не отправляем HTTP-запрос, как в обычном приложении на React, к какому-то REST API, который мы написали сами, верно?
00:57:12Вместо этого мы построили это так, будто это многостраничное приложение старой школы, где наша форма подключена к какому-то маршруту.
00:57:19И когда мы отправляем эту форму, я предполагаю, что за кулисами Inertia и Adonis создадут этот запрос и отправят его по этому маршруту.
00:57:28И всё будет обработано за нас, по сути.
00:57:31Так что нам не нужно отправлять запрос самостоятельно, ждать ответа, управлять состоянием.
00:57:37Нам не нужно этого делать здесь.
00:57:42Да.
00:57:44Каков твой мыслительный процесс, когда ты изучаешь новый фреймворк?
00:57:48Ты как бы сравниваешь его с другими фреймворками?
00:57:51Или ты относишься к нему как к чему-то абсолютно новому?
00:57:53Я думаю, ты автоматически всегда сравниваешь его немного с тем, что уже знаешь.
00:57:57Но, конечно, Adonis настолько отличается, например, от Next.js и так далее, что я не особо его сравниваю.
00:58:03Главное сравнение, которое я сделал изначально, — это то, что я понимаю или мне нужно понять, что это совершенно другая философия.
00:58:10Так что дело не только в маршрутизации и отрисовке компонентов, а в том, что это полноценный фреймворк с “батарейками в комплекте”.
00:58:18Поэтому я не особо его сравниваю.
00:58:19Я вижу его как нечто довольно новое.
00:58:21Я сравниваю его с Laravel немного, потому что это Laravel для JavaScript.
00:58:25И спасибо, Bleem, за очень приятный комментарий здесь.
00:58:29Рад, что тебе нравится контент.
00:58:32Хорошо.
00:58:34Общие типы.
00:58:35Фронтенд может по-прежнему полагаться на общие типы TypeScript, автоматически генерируемые Adonis.js.
00:58:40Они хранятся в директории .adonis.js клиента и включают определения типов для маршрутов, пропсов и так далее, чтобы мы могли использовать TypeScript.
00:58:48Start.
00:58:49Директория start содержит файлы, которые вы хотите импортировать во время жизненного цикла загрузки приложения.
00:58:55Например, файлы для регистрации маршрутов и определения обработчиков событий должны находиться в этой директории.
00:59:00Adonis.js не импортирует автоматически файлы из start.
00:59:03Adonis.js просто используется как соглашение для группировки похожих файлов.
00:59:06Хорошо.
00:59:07Так что в этой папке start у меня есть файл kernel.ts.
00:59:12О, да, я это уже видел.
00:59:14Верно, верно, верно, верно, верно, верно.
00:59:16Так что мы могли бы зарегистрировать здесь новое промежуточное ПО, я полагаю, и мы увидим, нужно ли нам это делать в рамках руководства.
00:59:24У нас есть папка тестов.
00:59:25У нас есть папка temp для временных файлов, таких как база данных.
00:59:28Ace.js — это точка входа для выполнения команд ace.
00:59:33У нас есть это здесь?
00:59:35Ace.
00:59:36Ace, да.
00:59:37Хорошо.
00:59:38Не модифицируйте этот файл.
00:59:39Хорошо.
00:59:41Да.
00:59:44Это манифест проекта?
00:59:46Использовать пакет lint.
00:59:48Использовать конфиг.
00:59:49Хорошо, понял.
00:59:51Настройка среды разработки.
00:59:54Приложения Adonis поставляются с полностью настроенной средой разработки.
00:59:57Так что, да, редактор кода.
01:00:01Да, я уже установил расширение Edge, но оно нам не понадобится, если я использую Inertia и React.
01:00:09TypeScript.
01:00:10Так что всё это должно быть настроено, насколько я понимаю.
01:00:12Так что я не хочу тратить на это время.
01:00:14Конфигурация и окружение.
01:00:18Конфигурация в Adonis организована в три отдельные системы, каждая из которых служит определенной цели.
01:00:23Файлы конфигурации содержат настройки вашего приложения в папке config.
01:00:28Переменные среды в .env содержат секреты времени выполнения и значения, которые меняются между средами.
01:00:33Имеет смысл.
01:00:34Кстати, касательно секретов, особенно со всеми этими атаками на цепочки поставок, моей рекомендацией было бы не хранить их в файлах .env.
01:00:41Я могу делать это для курса или чего-то подобного, потому что это быстро, и я удаляю это впоследствии в любом случае.
01:00:47Но для секретов, которые вы постоянно используете, я бы использовал сервис вроде InPhysical.
01:00:53Я знаю, мне не платят за это.
01:00:54Вы также можете использовать Doppler или что-то подобное.
01:00:57Это облачные сервисы.
01:00:58В InPhysical вы можете начать бесплатно.
01:01:01Да.
01:01:02А затем вы можете хранить свой секрет в облаке и подтягивать его через CLI.
01:01:06И если ваша машина будет скомпрометирована, ваши секреты не будут извлечены, по крайней мере, не так легко.
01:01:14Так что это просто небольшое примечание.
01:01:17Файл adonisrc.ts конфигурирует сам фреймворк.
01:01:20Хорошо.
01:01:20Так что файлы конфигурации — для приложения, а это — для самого фреймворка.
01:01:26Здесь мы могли бы, вероятно, изменить названия папок, в которых он ищет по умолчанию, и так далее.
01:01:33Конфигурация находится в каталоге config.
01:01:35Типичный проект Adonis включает несколько конфигурационных файлов.
01:01:38Я видел это.
01:01:39Вот как выглядит файл конфигурации базы данных.
01:01:42Конфиг почты.
01:01:43Заметьте, как этот файл конфигурации ссылается на переменные среды.
01:01:46Это правильный способ использования переменных среды.
01:01:49Да.
01:01:49Так что это имеет смысл.
01:01:50Так что, например, если у нас есть приложение, которое отправляет электронную почту, мы можем настроить, как отправляются электронные письма.
01:01:55Но что касается некоторых значений, мы помещаем их в файлы .env, чтобы не иметь их жестко закодированными здесь, в файлах конфигурации.
01:02:02Это просто для общей настройки, для корректировки параметров, а для конкретных значений, затем для секретов, мы загружаем их как переменные среды.
01:02:12Файлы конфигурации загружаются во время цикла загрузки приложения.
01:02:16Так что мы не используем шаблоны Edge, мы не используем переменные среды шаблонов Edge, .env, вероятно, загружается автоматически.
01:02:25App key — это специальная переменная среды, которую Adonis.js использует для шифрования cookie, подписания сессий и других криптографических операций.
01:02:35Так что мы собираемся запустить generate key, чтобы создать app key, но у нас он уже есть.
01:02:41Хорошо, мы это поняли.
01:02:46Так что я просто предположу, что настройки по умолчанию здесь подойдут.
01:02:49Я не хочу тратить этот стрим на просто корректировку файлов конфигурации.
01:02:53Так что давайте продолжим развертывание.
01:02:58Да, хорошо, но я не хочу делать развертывание.
01:03:00Я хочу построить FAQ, да, и теперь построить полнофункциональный, показать процесс разработки, веб-сайт витрины сообщества.
01:03:11В этом руководстве вы построите dev show.
01:03:14Да, я хочу это сделать.
01:03:17Но сначала вопросы.
01:03:21Как вы думаете, GitHub Actions — это главный виновник проблемы безопасности TanStack, или это вина TanStack?
01:03:27Технически, это вина TanStack, потому что они могли бы настроить всё так, чтобы этого не произошло, если я правильно помню.
01:03:38Но, конечно, если у вас есть система вроде GitHub Actions, которая сделала эту конкретную ошибку такой вероятной, это, конечно, тоже не очень хорошо.
01:03:50Теперь я скажу, что я не огромный эксперт в CICD.
01:03:55Я всегда использовал GitHub Actions много-много лет для разного рода автоматизаций.
01:04:00Но опять же, я не работаю в крупном предприятии, где у нас пять команд постоянно пушат в один и тот же репозиторий с кучей различных крайних случаев и сложных рабочих процессов.
01:04:12Так что я доволен GitHub Actions.
01:04:14Но опять же, я использую их в разных формах.
01:04:18Не все супер-супер простые, но определенно не самые сложные рабочие процессы, которые вы когда-либо видели.
01:04:29Я хочу спросить о вашем курсе по JavaScript.
01:04:31Плохо ли смотреть больше 90 видео и всё ещё не понимать?
01:04:33Если вы не понимаете ничего, это не хороший знак.
01:04:38Вероятно для меня тогда, я полагаю.
01:04:39Но сложно ответить вот так.
01:04:43Но что-то, я полагаю, должно щелкнуть, если вы смотрите видео по порядку.
01:04:51Но да, мне сложно, потому что я использую Windows, а вы использовали Apple.
01:04:54Но это должно иметь значение.
01:04:56JavaScript — это JavaScript.
01:04:57Так что я, но опять же, я не знаю, что, если вы говорите “не понимаю”, если вы не понимаете синтаксис JavaScript, это, на самом деле, одно и то же.
01:05:07Так что там Windows, Apple не должны быть проблемой.
01:05:10Привет, Макс.
01:05:11Спасибо за ваш огромный вклад в сообщество.
01:05:13Привет, и большое спасибо за, за очень приятные слова.
01:05:16Вы предпочитаете работать с React или Angular, или это зависит от проекта?
01:05:20Зависит от проекта.
01:05:21Но в наши дни я использую в основном React, также потому, что, конечно, это любимчик ИИ.
01:05:26И я использую много ИИ для, для кодинга, к лучшему или худшему.
01:05:33До ИИ у меня не было сильных предпочтений.
01:05:36Если что-то, я, вероятно, предпочитал Vue из-за синтаксиса и простоты использования, особенно Vue 2.
01:05:42Но да, эти дни давно прошли.
01:05:44Так что без разницы.
01:05:46Что, по-вашему, важно при изучении новых концепций парадигм фреймворков?
01:05:51Так что для меня действительно важно глубокое погружение.
01:05:54Я хочу понимать, как вещи работают под капотом.
01:05:57Я не хочу просто, я не хочу просто получить поверхностный ответ.
01:06:03Я хочу понимать, как вещи связаны, почему мы делаем определенные вещи определенным образом, когда использовать определенный подход.
01:06:10Я действительно пытаюсь ставить вещи под вопрос и погружаться немного глубже, если хотите это так назвать.
01:06:16Но теперь давайте построим это.
01:06:19Мы начинаем с Adonis.js Hypermedia.
01:06:22Так что я использую Inertia.
01:06:23Посмотрим, сможем ли мы всё равно заставить это работать.
01:06:27Да, у нас есть эти маршруты.
01:06:29Они у меня тоже есть, я полагаю.
01:06:34Где мы?
01:06:35Мы в start.
01:06:36Да, это папка start, маршруты.
01:06:39Да, у нас есть это тоже.
01:06:40Так что это выглядит так же.
01:06:43Набор инструментов дает нам маршруты регистрации, логина, логаута.
01:06:45Заметьте, как промежуточное ПО guest гарантирует, что только вышедшие из системы пользователи могут получить доступ к регистрации и логину, в то время как промежуточное ПО auth защищает маршрут logout.
01:06:53Мы уже выяснили это.
01:06:55Как работают контроллеры.
01:06:56Давайте посмотрим на контроллер регистрации, чтобы увидеть, как запросы проходят через приложение.
01:07:07Да, давайте взглянем на этот контроллер новой учетной записи в контроллерах приложения.
01:07:12Так что я использую Inertia, конечно, не Edge, но всё же.
01:07:19Каждый метод контроллера получает объект HTTP-контекста в качестве первого параметра.
01:07:26Этот здесь.
01:07:28Контекст содержит всё о текущем запросе, данные запроса, объект ответа, состояние аутентификации, рендерер представления и многое другое.
01:07:34Мы деструктурируем только те свойства, которые нам нужны.
01:07:39Метод create просто показывает форму регистрации.
01:07:42Да, так что я понял это.
01:07:44Мы здесь, в нашем случае, поскольку мы используем Inertia, мы получаем эту штуку Inertia.
01:07:48Там есть ещё вещи.
01:07:50Мы могли бы получить запрос, чтобы узнать, я не знаю, URL и тому подобные вещи.
01:07:57Но здесь мы используем этот объект Inertia для рендеринга представления.
01:08:01И здесь, для этого POST-маршрута, я использую, как кажется, да, мы извлекаем запрос, чтобы использовать метод validate для проверки тела запроса.
01:08:12Да.
01:08:17Вы могли заметить, что контроллер ссылается на модель пользователя и валидатор регистрации.
01:08:21Стартовый набор уже включает их.
01:08:23Мы изучим это в следующей главе.
01:08:27Хорошо.
01:08:30Когда контроллер вызывает рендерер представления, он ищет файл шаблона и рендерит его.
01:08:34Так что, да, мы поняли это.
01:08:35Представления находятся в папке resources.
01:08:38Попробуйте создать учетную запись.
01:08:39Да, я уже это сделал.
01:08:40Командная строка и REPL.
01:08:42Вы можете задаваться вопросом, почему мы рассматриваем CLI и REPL вместо того, чтобы сразу перейти к созданию функций.
01:08:46Вот почему.
01:08:46На протяжении этого руководства вы будете постоянно использовать команды ACE для генерации контроллеров, моделей и других файлов.
01:08:51Знакомство с CLI сейчас предотвращает прерывание потока позже.
01:08:54Хорошо.
01:08:55Мы можем увидеть доступные команды с помощью node ace list.
01:08:59Давайте сделаем это.
01:09:02Привет.
01:09:05Хорошо.
01:09:06Так что у нас есть куча команд, куча встроенных команд, которые мы можем запустить.
01:09:11Установка и настройка одного или нескольких пакетов Adonis.
01:09:14Сборка, извлечение, команды базы данных для запуска сидеров.
01:09:19Генерация ключа.
01:09:21Вывод списка наших маршрутов.
01:09:23Создание вещей вроде событий, для которых мы хотим настроить обработчик.
01:09:29Или создание нового промежуточного ПО, или модели.
01:09:32Хорошо.
01:09:32Да.
01:09:38REPL.
01:09:39Да.
01:09:40Я на самом деле прыгну вперед.
01:09:42Я чувствую риск.
01:09:54В этой главе вы создадите модели и миграции для ресурсов постов и комментариев.
01:09:59Установка связей.
01:10:01Генерация тестовых данных.
01:10:01Хорошо.
01:10:02В этой главе мы познакомимся с Lucid, AdonisJS и SQL ORM.
01:10:06Вместо написания SQL-запросов вручную, вы будете работать с классами JavaScript, называемыми моделями, которые представляют ваши таблицы базы данных.
01:10:11Я уже говорил об этом раньше.
01:10:14Важное различие.
01:10:15Модели определяют, как вы взаимодействуете с данными, но они не меняют структуру базы данных.
01:10:20Это задача миграций.
01:10:21Да.
01:10:21Итак, у нас есть модель.
01:10:22Мы будем использовать модель в нашем коде.
01:10:24Для взаимодействия с данными.
01:10:25Но для этого нам нужна таблица в базе данных.
01:10:27И чтобы её создать, нам нужна так называемая миграция.
01:10:31Это как небольшой скрипт, можно сказать.
01:10:33Или чертёж для настройки базы данных, чтобы создать нужную нам таблицу.
01:10:37И миграция создаётся на основе модели.
01:10:40На основе класса модели.
01:10:42Так это работает в Laravel.
01:10:43И я понимаю, что в Adonis это работает точно так же.
01:10:49Итак, давайте добавим модель Post.
01:10:54С помощью команды node ace make:model post.
01:11:01И это создаст файл модели post.ts.
01:11:05И также автоматически создаст новый файл миграции.
01:11:09Потому что, как я уже сказал, нам нужны и модель, и миграция.
01:11:11Итак, теперь у нас есть модель post.
01:11:13Пока что пустой класс.
01:11:19Возможно, это просто ошибка TypeScript в моей IDE.
01:11:26Или нет.
01:11:27Думаю, её у нас нет.
01:11:28Потому что я ещё не настроил миграцию.
01:11:33Схему.
01:11:34Форму таблицы.
01:11:41Определите структуру таблицы в миграции.
01:11:43Верно.
01:11:43Итак, нам нужно это сделать.
01:11:45Позвольте мне скопировать это.
01:11:48И перейдем к этому посту.
01:11:53Файл миграций.
01:11:54Базовая схема.
01:11:56Да.
01:11:56Это то, что нужно.
01:11:59Изначально она настраивает базовую таблицу с названием posts.
01:12:07И добавляет только ID и временные метки.
01:12:10А мы добавляем эти три строки.
01:12:14Так что я могу просто скопировать их.
01:12:16Вставить их сюда.
01:12:18Чтобы дать каждому посту заголовок, URL и краткое содержание.
01:12:24Как оказалось.
01:12:25И мы установили not nullable, чтобы значения были обязательными.
01:12:28Они не должны быть пустыми.
01:12:30Хорошо.
01:12:31Теперь нам, вероятно, нужно это запустить.
01:12:34Да.
01:12:34Часть “up” запускается для создания.
01:12:36Часть “down” запускается для удаления таблицы.
01:12:39Создание модели комментария.
01:12:40Давайте создадим модель комментария.
01:12:43Итак, давайте.
01:12:45На самом деле, позвольте мне остановить сервер разработки.
01:12:47Потому что нам все равно нужно будет перезапустить его, чтобы изменения вступили в силу, я полагаю.
01:12:51Итак, снова создадим еще одну модель.
01:12:53Модель комментария.
01:12:54Прямо как раньше.
01:12:56Получили новый файл миграции.
01:12:57Получили новый...
01:13:01Где это?
01:13:02Новая модель.
01:13:03Модель комментария здесь.
01:13:04И в файле миграции.
01:13:06Снова базовый скелет.
01:13:09И что мы здесь добавляем?
01:13:10Только одну строку, как кажется.
01:13:13Для контента.
01:13:18Хорошо.
01:13:21А теперь мы можем запустить их, чтобы применить к базе данных и добавить эти таблицы.
01:13:27Выглядит хорошо.
01:13:29А теперь посмотрим.
01:13:31Запуск сервера разработки снова работает.
01:13:35И теперь эта ошибка здесь тоже исчезла.
01:13:36Потому что теперь, когда мы применили миграции, он, вероятно, создал эти типы.
01:13:47Да.
01:13:48Database schema TS была обновлена.
01:13:51Так что это здесь, в папке database, schema TS.
01:13:56Так что этот файл, по сути, управляется нами.
01:13:58Теперь в нем есть схемы, которые были созданы для нас Adonis.
01:14:02С помощью этой ace команды в конце.
01:14:04Итак, спасибо за ваш ответ, Макс.
01:14:11Я купил несколько ваших курсов.
01:14:12Это очень помогло мне в карьере разработчика ПО.
01:14:16Да.
01:14:17Спасибо огромное.
01:14:18Спасибо большое за участие в курсах и за очень приятные слова.
01:14:21Я очень рад слышать, что контент был полезен.
01:14:24И что я смог стать небольшой частью вашей карьеры.
01:14:27Спасибо большое.
01:14:31Итак, давайте посмотрим, как мы можем добавить связи.
01:14:33Потому что, очевидно, мы хотим связь между нашими комментариями и нашими постами.
01:14:37Мы хотим, чтобы у каждого поста был потенциально один или несколько комментариев.
01:14:44И каждый комментарий принадлежит ровно одному посту.
01:14:47Итак, это отношение один-ко-многим.
01:14:54Комментарии принадлежат постам, а посты принадлежат пользователям.
01:14:57Да, верно.
01:14:57Нам это тоже нужно.
01:14:58Итак, создайте миграцию для внешних ключей.
01:15:01Следующая команда создаст новый файл миграции, который изменит наши существующие таблицы.
01:15:04Хорошо, давайте посмотрим.
01:15:06Что это делает?
01:15:09Make migration add foreign keys.
01:15:11Хорошо, это просто дополнительный файл миграции.
01:15:13Раньше у нас были модели, которые идут с файлом миграции.
01:15:16Теперь мы используем просто файл миграции.
01:15:22Потому что нам не нужна модель и класс.
01:15:25Но нам нужна миграция, чтобы мы могли настроить базу данных и добавить новые столбцы в некоторые таблицы.
01:15:40И мы хотим добавить столбцы для настройки этих отношений, потому что отношения в базе данных SQL, конечно, просто выражаются путем добавления столбцов, где вы говорите, что у этого комментария есть ID пользователя и ID поста и так далее.
01:15:53Итак, позвольте мне скопировать это.
01:15:55Итак, позвольте мне скопировать это.
01:15:56Это внешние ключи к постам.
01:16:00Это то, что я создал?
01:16:05Добавить внешние ключи.
01:16:11Секундочку.
01:16:22О, теперь будет.
01:16:23Я разве не запускал?
01:16:25Нет, это вот эта.
01:16:28Хорошо, так что у него просто другое имя файла.
01:16:31Ну, это нормально.
01:16:34Итак, давайте вставим это.
01:16:35Что мы делаем?
01:16:37Мы говорим, что в таблице posts мы добавляем столбец user_id, который имеет тип integer, unsigned, только положительные значения.
01:16:45Это не null.
01:16:45И мы настраиваем связь внешнего ключа.
01:16:48И если пользователь будет удален, мы также удаляем посты.
01:16:51Для комментария мы также связываем его с пользователями, но также и с постами, потому что каждый комментарий, конечно, принадлежит посту.
01:16:58А потом у нас есть миграции вниз, чтобы по сути отменить их.
01:17:01Хорошо.
01:17:03Запустить их.
01:17:07Запустить их.
01:17:11Сервер разработки запускается.
01:17:13И определить связь в модели поста.
01:17:15Теперь, когда в базе данных есть столбцы внешних ключей, давайте обновим модель, чтобы определить эти связи.
01:17:20Итак, я скопирую это.
01:17:22Перейду к моей модели поста, которая сейчас в основном пуста, и вставлю это туда.
01:17:27И теперь в этом классе мы объявляем это отношение, добавляя по сути свойство comments, которое не имеет значения, но мы добавляем этот декоратор.
01:17:43Итак, мы просто добавляем свойство, чтобы иметь возможность добавить декоратор, потому что, похоже, в Adonis мы настраиваем отношения через декораторы, предоставленные Adonis, и говорим, что у поста много комментариев и он принадлежит пользователю.
01:17:57И это что-то, я думаю, это своего рода такая же формулировка в Laravel.
01:18:02Так что довольно легко читать и понимать.
01:18:05Эта часть может быть немного странной, что мы просто объявляем переменную, просто объявляем свойство.
01:18:11И нам нужно declare, потому что без этого мы получаем некоторые проблемы от TypeScript, что у него нет начального значения.
01:18:18С declare мы этого не получаем.
01:18:20Итак, вот и все.
01:18:22И нам также нужны связи в модели комментариев.
01:18:26Так что давайте вставим его туда.
01:18:28И здесь мы в основном говорим, что комментарий принадлежит посту, он принадлежит пользователю.
01:18:31Так что у вас есть has и belong, в зависимости от того, с какой стороны вы на это смотрите.
01:18:36И вы всегда настраиваете оба.
01:18:39Хорошо.
01:18:40Итак, теперь мы получаем это.
01:18:41Мы не добавили обратный has many в модель пользователя, потому что они нам не нужны в этом уроке.
01:18:46Вы можете добавить их позже, если вашему приложению нужно будет запрашивать посты или комментарии со стороны пользователя.
01:18:51Хорошо.
01:18:52Похоже, мы никогда не будем искать все посты пользователя в этом уроке.
01:18:58Так что нам не нужно настраивать связи, но нам нужно было бы их настроить, если бы мы хотели сделать запрос на все посты пользователя.
01:19:04Но, похоже, здесь мы просто будем делать запрос на все посты, и мы просто хотим отобразить, к какому пользователю они принадлежат.
01:19:16Чувак, этот фреймворк выглядит так, будто у Angular и Nest появился ребенок.
01:19:20Я полагаю, что большие и сложные фреймворки все еще актуальны в наши дни.
01:19:24Так что, я думаю, этот фреймворк, в теории, мог бы быть довольно крутым, потому что в нем так много всего встроено.
01:19:30И поначалу это определенно выглядит немного ошеломляюще, я полагаю.
01:19:33Но, огромное преимущество заключается в том, что вам, по сути, ничего не нужно добавлять.
01:19:39Не совсем ничего, но вам не нужно добавлять много вещей, и для многих приложений вам, вероятно, не нужно ничего добавлять, чтобы это работало для широкого спектра приложений.
01:19:48Я имею в виду, я большой поклонник Next.js, Tanstack, Start, и я никогда раньше не использовал Adonis.js.
01:19:54Так что я не могу сказать вам: эй, это потрясающе, пожалуйста, используйте это, верно?
01:19:56Я сам это не использовал.
01:19:58Но, конечно, когда вы используете Next.js или Tanstack, или что угодно, вещи Angular, вам всегда приходится добавлять дополнительную библиотеку для аутентификации.
01:20:07Для работы с базой данных вам нужно добавлять дополнительные библиотеки, потенциально ORM, Prisma, что угодно.
01:20:14Так что вам приходится сшивать вместе все эти библиотеки, и особенно в наши дни с атаками на цепочки поставок, это может быть раздражающе.
01:20:21И даже до этого, с обслуживанием и всем таким.
01:20:23Так что, в теории, это должно быть здорово, да.
01:20:26Вы работаете без ИИ, чувствуя себя хорошо и одновременно ностальгируя.
01:20:30О, да.
01:20:31Есть ностальгическое чувство в этом.
01:20:33Теперь, очевидно, я не использую ИИ здесь, потому что хочу понять, как это работает и что здесь происходит.
01:20:38И я считаю, что это важно, если вы изучаете что-то новое, даже в наши дни.
01:20:42Это также не было бы веселой прямой трансляцией, если бы он просто Vibe-кодил.
01:20:47И, да, в любом случае вы можете зайти только так далеко с Vibe-кодингом.
01:20:52Теперь, когда наши модели и таблицы базы данных готовы, нам нужно заполнить их тестовыми данными для разработки и тестирования.
01:20:57Фабрики действуют как чертежи для создания экземпляров модели, заполненных реалистичными фейковыми данными.
01:21:03Вы определяете чертеж один раз.
01:21:04Хорошо.
01:21:05Итак, мы хотим создать фабрику постов, чтобы наштамповать несколько фейковых постов.
01:21:10Итак, мы запускаем команду make factory.
01:21:14Это дает нам файл фабрики поста, где мы теперь, по сути, определяем, как мы хотим генерировать посты, я полагаю.
01:21:21Итак, давайте скопируем это сюда и взглянем.
01:21:25Итак, мы говорим, что хотим создать фейковый пост.
01:21:30У нас есть куча заголовков, из которых этот инструмент faker может выбирать при генерации постов.
01:21:37И какой-то выдуманный URL, и какие-то выдуманные абзацы Lorem Ipsum, которые он должен добавить.
01:21:45Так что просто программный способ быстрого добавления фейковых данных.
01:21:48Очевидно, в наши дни мы могли бы также использовать ИИ для этого.
01:21:51Но давайте пойдем старым путем и дешевле, потому что нет токенов.
01:21:56Давайте также создадим фабрику комментариев.
01:22:02Вот и мы.
01:22:03И давайте скопируем этот код сюда.
01:22:06А здесь мы просто выводим фиктивный абзац lorem ipsum.
01:22:11А теперь нам нужен сидер.
01:22:12Итак, у нас есть фабрика, которая может генерировать фейковые данные.
01:22:15Но что нам делать с этими фейковыми данными?
01:22:17Мы хотим внести их в базу данных.
01:22:19И вот тут-то и пригодится сидер.
01:22:23Итак, мы хотим его создать.
01:22:24И это общие концепции.
01:22:26Фабрики, сидеры.
01:22:27Вы знаете их не только по Adonis.
01:22:28Вы знаете их по Laravel.
01:22:29Или же вы можете использовать эти концепции в любой настройке.
01:22:37Также в приложении XJS у вас может быть база данных, которую вы хотите наполнить какими-то данными.
01:22:41Очевидно, что команды node ace специфичны для Adonis.
01:22:45Но теперь мы создаем сидер.
01:22:47И давайте взглянем на сидер постов.
01:22:49Итак, это файл, который мы можем запустить, чтобы внести начальные данные в базу данных.
01:22:54И поэтому нам нужно определить, что мы хотим там сделать.
01:22:57И я полагаю, что мы хотим здесь создать несколько фиктивных постов и комментариев, связать их, а затем запустить что-то, чтобы внести это в базу данных.
01:23:07Однако, вот как это выглядит в Adonis.
01:23:10Так что давайте вставим его и посмотрим.
01:23:13Итак, мы ищем или вызываем ошибку.
01:23:17Мы пытаемся найти пользователя.
01:23:19И это должно привести к ошибке.
01:23:21Потому что там не сказано, что он его создает, а у нас нет этого пользователя.
01:23:25Поэтому мы пытаемся найти этого пользователя.
01:23:26Нам придется его создать.
01:23:28Затем мы объединяем этого пользователя.
01:23:33И мы создаем много новых постов и, по сути, привязываем их к этому пользователю с помощью этой команды.
01:23:37А затем для каждого из этих постов мы создаем несколько фиктивных комментариев, которые мы также привязываем к этому посту и к этому пользователю.
01:23:46И мы создаем случайное количество комментариев плюс три.
01:23:51Итак, по крайней мере три комментария, но всего до шести комментариев для каждого поста.
01:24:02Итак, от трех до шести комментариев.
01:24:06Сначала мы выбираем пользователя с этим адресом электронной почты.
01:24:09Это пользователь, которого мы создали в предыдущей главе с помощью O.
01:24:12Поэтому я создам этого пользователя сам.
01:24:15Позвольте мне быстро это сделать.
01:24:19Давайте запустим это.
01:24:23Ну, я еще не пробовал запускать сидер.
01:24:26Так что это должно работать.
01:24:27Но это неправильно.
01:24:28Позвольте мне быстро зарегистрироваться.
01:24:34Да, да, да.
01:24:36Нет, не это.
01:24:37Давайте.
01:24:39Я воспользуюсь.
01:24:44Хорошо.
01:24:45Итак, я воспользуюсь другим адресом электронной почты.
01:24:47Очевидно, я воспользуюсь.
01:24:50Test at example.com.
01:24:52Хорошо.
01:24:53Так что мы получили это.
01:25:02Да, пожалуйста, продолжай.
01:25:03Такие стримы.
01:25:03Нам они нравятся.
01:25:04Да, я определенно хочу продолжать их.
01:25:06И, кстати, я планирую проводить такие стримы каждый четверг.
01:25:13На следующей неделе я не смогу этого сделать.
01:25:16У меня там есть другие встречи.
01:25:18Но, в целом, каждый четверг в это время, начиная с 17:00 по центральноевропейскому летнему времени, таков мой план.
01:25:26Так что, как по мне, Anthropic действительно хочет продвигать свои собственные инструменты.
01:25:40Они хотят продвигать Claude Code и ничего больше.
01:25:42Они хотят привязать людей к нему.
01:25:43Так что посмотрим.
01:25:45Я не уверен, что мы сможем использовать Claude во всех других инструментах.
01:25:51По крайней мере, не с подпиской, оплачивающей токены.
01:25:55Это, вероятно, будет возможно, потому что вы просто используете API.
01:25:58Но это, конечно, также очень дорого.
01:26:02Итак, давайте теперь запустим сидер.
01:26:06Отмените этот сервер.
01:26:09Запустите его.
01:26:10И это теперь создало фиктивные данные.
01:26:12И мы должны быть в состоянии увидеть их уже сейчас, даже без готового приложения.
01:26:17В базе данных мы можем видеть таблицы постов и комментариев.
01:26:21В таблице пользователей у меня есть мой пользователь.
01:26:23И в таблице постов у нас есть фиктивные посты.
01:26:27А в таблице комментариев у нас есть фиктивные комментарии.
01:26:33И каждый комментарий привязан к определенному пользователю и ID поста.
01:26:36Очевидно, что у нас здесь только один пользователь.
01:26:38Так что все они привязаны к этому одному пользователю.
01:26:40Это то, что мы написали в сидере.
01:26:41А затем для постов мы видим здесь, что у нас есть пост с, ну, пятью комментариями.
01:26:47Здесь у нас есть один с тремя комментариями и так далее.
01:26:50Так что это соответствует тому, что мы написали.
01:26:52Хорошо.
01:26:53Так что я понимаю, что мы здесь сделали.
01:26:55Запрос данных с помощью REPL этого не сделает.
01:26:57Мы уже видели, что они там есть.
01:27:00Но, да.
01:27:01Но мы взглянем на код здесь.
01:27:02Итак, интересно, конечно, что при таком подходе на основе моделей вы не пишете SQL-запросы или что-то подобное.
01:27:10Вместо этого вы используете свою модель или получаете доступ ко всем моделям.
01:27:17Затем ваша модель, и это существует, потому что мы зарегистрировали модель с этим именем.
01:27:20А затем вы можете использовать такие методы, как all, чтобы получить все посты.
01:27:24Или, как мы видим здесь, вы можете писать запросы, где у вас есть предложение where, чтобы ограничить количество постов.
01:27:30И именно так работает ORM.
01:27:32Вы программно запрашиваете свои данные и не пишете SQL-операторы.
01:27:37Теперь, честно говоря, я не большой фанат ORM, или я ничего не имею против них, но я их обычно не использую.
01:27:46И, особенно в наше время с ИИ, я нахожу написание необработанных SQL-запросов проще, чем когда-либо.
01:27:52Поэтому я обычно использую необработанные SQL-запросы в своих приложениях.
01:27:58Я не использую ORM.
01:28:00Потому что, конечно, у вас есть полная свобода, если вы пишете необработанные запросы.
01:28:06И даже до появления ИИ многие запросы были не такими уж сложными, честно говоря.
01:28:10Даже с JOIN, это не так сложно.
01:28:13И, конечно, SQL-запросы могут стать довольно сложными, и ИИ может ошибиться.
01:28:18Но, по моему опыту, он довольно неплохо справляется с большинством запросов, включая более сложные.
01:28:22Так что это просто мои пять копеек.
01:28:24Но здесь мы используем ORM, так что я придержусь его.
01:28:29Маршруты, контроллеры и представления.
01:28:32В предыдущей главе мы создали модели постов и комментариев с их таблицами базы данных и связями.
01:28:37Теперь мы оживим эти модели, создав страницы, на которых пользователи могут видеть посты.
01:28:46Ваши посты и комментарии существуют только в базе данных.
01:28:49Сервер уже запущен.
01:28:52Итак, теперь мы хотим создать новый контроллер.
01:28:54И идея этого фреймворка, как я понимаю, заключается в том, что у вас есть маршрут, контроллер и представление.
01:29:02Так что старый добрый MVC, если кто-то из вас помнит.
01:29:07Model View Controller.
01:29:09Это довольно старый способ структурирования приложений, не только веб-приложений.
01:29:18Но старый не значит плохой, просто чтобы прояснить это.
01:29:24Но вы не увидите этого, на самом деле, во всех этих приложениях на Next.js и так далее, я полагаю.
01:29:30Так что да.
01:29:31На другой вкладке позвольте мне запустить это, создать новый контроллер постов.
01:29:38Вот он, пустой файл, и в нем мы теперь регистрируем методы, которые затем определяют, что произойдет в четырех разных маршрутах.
01:29:44Опять же, я вставлю это, чтобы сэкономить время.
01:29:47И что у нас здесь есть, так это метод index.
01:29:52Мы получаем здесь какой-то HTTP-контекст, который, опять же, является той штукой, которая дает нам всевозможные данные.
01:29:57И, на самом деле, нам нужно подправить это, потому что это здесь для, мне нужно использовать Inertia.
01:30:05Мне нужно использовать Inertia, и, конечно, нам нужно будет добавить этот компонент.
01:30:09Но что мы здесь делаем, так это используем наш класс post, так что, из нашего файла моделей, верно?
01:30:16Так что здесь класс post, который мы определили ранее.
01:30:20И, опять же, это ORM в действии, где мы создаем запрос.
01:30:24Предварительная загрузка пользователя, вероятно, там есть, так что мы загружаем его один раз, а затем не снова для каждого поста, который мы выбираем, я предполагаю.
01:30:32А затем мы сортируем посты, очевидно, по дате создания, в порядке убывания.
01:30:38Так что первый пост — самый молодой, самый недавний.
01:30:45Так что мы рендерим, и, следовательно, нам нужно будет добавить это.
01:30:53Определение маршрута.
01:30:56Так что теперь мы должны, ну, маршрут такой, что мы идем к запуску маршрутов.
01:31:03И здесь мы добавили здесь.
01:31:07Мы могли бы добавить его куда угодно, конечно.
01:31:10И почему это не работает?
01:31:12Почему это не работает?
01:31:13Мне нужно перезапустить сервер разработки или что-то вроде этого?
01:31:16Ой, это неправильно.
01:31:18О, у меня не был запущен сервер разработки.
01:31:21Это моя ошибка.
01:31:22Так что теперь давайте запустим его, и, надеюсь, да.
01:31:25Теперь это создано автоматически.
01:31:26Так что, по сути, Adonis создает кучу определений типов на лету.
01:31:31Так что теперь это здесь.
01:31:34Мы говорим Adonis, что для запросов, get-запросов к /posts.
01:31:40Мы хотим вызвать метод index в контроллере posts.
01:31:43И это, конечно, этот метод.
01:31:47Теперь нам понадобится представление.
01:31:50И мы можем сделать новое представление.
01:31:53Я не знаю, является ли это правильной командой, если я хочу иметь представление Inertia.
01:31:56Так что посмотрим.
01:31:59Я могу запустить node as list, чтобы увидеть, что я могу сделать.
01:32:04Так что я могу сделать представление, но это файл шаблона edge.js.
01:32:08Я этого не хочу.
01:32:11Может быть, мне придется создавать его вручную.
01:32:20Похоже, мне придется создавать его вручную, но это не должно быть слишком сложно.
01:32:24Так что давайте перейдем к страницам Inertia.
01:32:29Так что там я теперь добавлю посты.
01:32:31И там добавить файл index.js, верно?
01:32:34А затем я экспортирую функцию по умолчанию.
01:32:38И я назову это posts.
01:32:41И я скажу что-то вроде моих постов.
01:32:44Так что просто обычный компонент React.
01:32:50Теперь эта ошибка исчезла.
01:32:51Потому что теперь я добавил эту штуку, верно?
01:32:55Так что я добавил папку posts с файлом index.js.
01:32:58И это именно то, что я сказал здесь.
01:32:59Так что вот как это связано.
01:33:02И там, на данный момент, конечно, с запущенным сервером разработки,
01:33:05Я могу пойти сюда, ввести /posts, и я вижу свои посты здесь.
01:33:09Так что это работает.
01:33:10И теперь, конечно, нам просто нужно получить данные из контроллера в этот компонент.
01:33:20И, на самом деле, мы уже делаем это здесь, я полагаю, как props.
01:33:23Так что вопрос в том, если мы здесь получаем это.
01:33:30Так как же мне...
01:33:33О, нет, я думаю, нам нужно сделать детей.
01:33:36Как это работает в другом файле здесь?
01:33:40Есть ли у нас какой-нибудь файл, где мы передаем данные?
01:33:45Нет.
01:33:46У нас нет, нет, нет, нет.
01:33:50В макете, верно?
01:33:52Дети.
01:33:54Так что я полагаю, это то, что мне нужно.
01:33:58Но я никогда раньше этого не делал.
01:34:00Так что нам придется разобраться с этим.
01:34:19Разве это не то, что у нас здесь есть?
01:34:23О, да, моя ошибка, моя ошибка, моя ошибка.
01:34:25Это не валидный код TypeScript, конечно.
01:34:27Это должно быть так.
01:34:30Хорошо.
01:34:30Так что теперь нам нужно добавить эти импорты.
01:34:36Импорт.
01:34:38Так что я полагаю, это правильно.
01:34:40Это то, что у нас здесь есть?
01:34:41Данные, сгенерированные данные.
01:34:42Да.
01:34:43Окей.
01:34:45Окей.
01:34:45Так, ну давайте посмотрим.
01:34:46Можем мы добавить сюда какой-нибудь фрагмент?
01:34:50И сделать что-то вроде.
01:34:54Children.
01:34:57Props.
01:34:59Хм.
01:35:02User.
01:35:03Да, может это не разделяемые пропсы.
01:35:04Как мне получить.
01:35:06Мне, вероятно, придется углубиться в.
01:35:10Давайте посмотрим.
01:35:11Мне, наверное, придется залезть в документацию Inertia.
01:35:15Руководства.
01:35:17Где здесь Inertia?
01:35:19Как мне передать пропсы в мои компоненты?
01:35:24Мне нужно.
01:35:25Нужен ли мне трансформер?
01:35:29Использовать трансформер для сериализации экземпляров модели в простые объекты.
01:35:33Понял.
01:35:34Понял.
01:35:35Понял.
01:35:37Окей.
01:35:37Так что я сейчас немного схитрю.
01:35:40Привлеку сюда ИИ.
01:35:44Эм.
01:35:48Создаю Adonis.
01:35:51JS приложение.
01:35:53Мне нужно получить мои посты.
01:35:56Вижу.
01:35:57Контроллер постов.
01:36:02В мою Inertia постов.
01:36:04Ой.
01:36:05Вижу, что вам это не читаемо.
01:36:10Окей.
01:36:10Окей.
01:36:10Секундочку.
01:36:18Окей.
01:36:18Создаю Adonis.
01:36:20JS приложение.
01:36:21Мне нужно получить мои посты.
01:36:24Из моего контроллера постов.
01:36:27Добавить.
01:36:28Ой.
01:36:28Добавить посты.
01:36:30Контроллер.
01:36:32В мои посты.
01:36:35Вид.
01:36:35Inertia.
01:36:37Вид.
01:36:39Так, это индекс в папке постов здесь.
01:36:45И я просто дам ссылки на эти страницы.
01:36:48Пожалуйста, посмотрите.
01:36:50И.
01:36:56Чтобы помочь мне сделать это.
01:36:59И давайте посмотрим, сможет ли он с этим разобраться.
01:37:03Эм.
01:37:03ORM хороши для трансформации схем и совместной работы.
01:37:07Эм.
01:37:08Да.
01:37:09И опять же.
01:37:09Я не говорю.
01:37:10Что ORM - это плохо.
01:37:11Просто.
01:37:11Просто это не то, что мне нужно для моего проекта.
01:37:14Но опять же.
01:37:14Я не работаю в каких-то больших командах или что-то в этом роде.
01:37:18Эм.
01:37:18Я.
01:37:19Я точно.
01:37:20Говорю.
01:37:21Что использую миграции.
01:37:23Так что.
01:37:23Это не так.
01:37:24Что я не.
01:37:25Использую миграции.
01:37:26Или что-то вроде этого.
01:37:27Эм.
01:37:28Я просто также.
01:37:29Пишу их сам.
01:37:30Или прошу.
01:37:31LLM написать их.
01:37:32Так что миграции очень полезны.
01:37:34Мне просто не нужна часть с ORM.
01:37:36Я задавался вопросом.
01:37:36Спросить вас о том.
01:37:37Хорошо ли.
01:37:38Wipe coding или нет.
01:37:39Я не думаю.
01:37:40Wipe coding.
01:37:41Подходит для.
01:37:42Чего-то серьезного.
01:37:43Но.
01:37:44Wipe coding.
01:37:44Определенно очень хорош.
01:37:45Если вам просто нужен.
01:37:46Быстрый.
01:37:47Утилитарный инструмент.
01:37:48Или если вам просто нужно.
01:37:48Сделать работу.
01:37:50Верно.
01:37:50Если вы создаете какое-то ПО.
01:37:51Которое продаете.
01:37:52Если вы.
01:37:53Работаете над чем-то серьезным.
01:37:55Которое вы планируете распространять.
01:37:56Или в вашей работе.
01:37:57Wipe coding.
01:37:58Просто заставляет вас терять.
01:37:59Весь след.
01:38:00Вы не понимаете.
01:38:01Что происходит в кодовой базе.
01:38:02И в конечном итоге.
01:38:03Вы упретесь в стену.
01:38:04И не будете.
01:38:04Знать как продолжить.
01:38:06Так что.
01:38:07Не заботиться о коде.
01:38:08Не является хорошим решением.
01:38:09Для.
01:38:09Для таких ситуаций.
01:38:11Но опять же.
01:38:11Если вам просто нужен.
01:38:13Эм.
01:38:13Быстрый.
01:38:15Инструмент.
01:38:16Который вы запускаете на своей машине.
01:38:17Или что-то вроде того.
01:38:18Вы можете не заботиться о.
01:38:19Эм.
01:38:20О всех.
01:38:21Деталях.
01:38:23И всем таком.
01:38:24Так что да.
01:38:25Vipe coding может быть хорош там.
01:38:26И да.
01:38:26Live coding - это всегда.
01:38:28Всегда вызов.
01:38:29Но мы посмотрим, сможет ли ИИ разобраться.
01:38:31Похоже, он тут борется с некоторыми ошибками линтера.
01:38:36Но да.
01:38:38Я просто использую ИИ.
01:38:40Кстати.
01:38:40Обычно я бы погрузился сюда.
01:38:41И написал бы сам.
01:38:44Но мне нужно уходить через 20 минут.
01:38:47И я предпочел бы получить готовый код сейчас.
01:38:49И проработать его.
01:38:51И сейчас.
01:38:52Чтобы мы могли после этого продолжить здесь.
01:38:54Это главная причина.
01:38:56Так что окей.
01:38:56Теперь он что-то сделал.
01:38:58И давайте сначала посмотрим, работает ли это.
01:39:00Прежде чем я начну объяснять.
01:39:02А потом увидим, что он сделал.
01:39:04Но выглядит хорошо.
01:39:05Стилизация совершенно ужасная.
01:39:07Но как мы видим.
01:39:10У меня тут рендерится куча постов.
01:39:12И я вижу, что они связаны с моим пользователем.
01:39:16Так что.
01:39:17Отправка данных из контроллера.
01:39:19Кажется, работает.
01:39:19Так что давайте теперь посмотрим.
01:39:20Как это работает.
01:39:22И опять же.
01:39:22Я дал ему ссылки на официальную документацию.
01:39:24Так что это просто.
01:39:28Это просто.
01:39:31То, чему нас учит документация.
01:39:34Итак, в контроллере постов.
01:39:36Мы получаем посты.
01:39:38Единственное, что изменилось здесь.
01:39:39Это, по сути.
01:39:40То, что мы.
01:39:41Передаем наши посты.
01:39:42Но не в сыром виде, как здесь.
01:39:43А вместо этого.
01:39:44С помощью трансформатора постов.
01:39:45Это новая вещь, которую он добавил.
01:39:47Так что этот файл новый.
01:39:48Трансформатор постов.
01:39:50И это класс.
01:39:51Который расширяет базовый трансформатор.
01:39:53Окей.
01:39:53И там.
01:39:54Мы просто описываем.
01:39:55Как сериализовать пост.
01:39:56Так что мы говорим.
01:39:57Эй.
01:39:58Возьми все эти свойства.
01:40:01И.
01:40:02Для пользователя.
01:40:03Также трансформируй пользователя.
01:40:04Так что по сути.
01:40:05Я имею в виду, в этом случае.
01:40:06Трансформация должна быть довольно простой.
01:40:08Скорее всего, она просто берет
01:40:11ISO.
01:40:12Формат.
01:40:13Даты здесь.
01:40:14А остальные необработанные данные
01:40:15можно упаковать
01:40:16в объект JavaScript.
01:40:17Вот так.
01:40:18Так что это по сути
01:40:19описывает,
01:40:20как конвертировать
01:40:21класс,
01:40:21который может содержать вещи,
01:40:23которые нельзя легко конвертировать
01:40:25в JSON.
01:40:26Как конвертировать
01:40:27это в JSON.
01:40:28Это,
01:40:28как я понимаю, работа трансформатора.
01:40:30Как я это понимаю.
01:40:33Окей.
01:40:33Так что мы задаем посты здесь.
01:40:34И теперь
01:40:35во вьюхе.
01:40:40Во вьюхе
01:40:41мы получаем страницу.
01:40:42Окей.
01:40:43Мы просто настраиваем
01:40:43пропсы страницы вот так.
01:40:44Окей.
01:40:45Мы просто настраиваем
01:40:46тип пропсов.
01:40:47Тип TypeScript.
01:40:48Используя пропсы Inertia.
01:40:51Вместо
01:40:51некоторых сгенерированных типов.
01:40:54Или
01:40:55DAI.
01:40:56Добавить это.
01:40:57Я полагаю,
01:40:58это какие-то
01:40:58стандартные типы.
01:41:00Не
01:41:00не сгенерированные ИИ.
01:41:02И
01:41:02мы просто говорим:
01:41:03Окей,
01:41:03эй.
01:41:04Здесь
01:41:04у нас будет ключ поста.
01:41:06И
01:41:06это
01:41:07типа.
01:41:08Да.
01:41:08Так что это
01:41:09автоматически сгенерированный
01:41:10тип здесь
01:41:10для
01:41:11наших постов.
01:41:12И я полагаю,
01:41:13этот тип
01:41:14генерируется
01:41:15на основе того,
01:41:15как мы трансформируем
01:41:16посты.
01:41:17Так что пост здесь,
01:41:20эта штука,
01:41:23да,
01:41:24исходит из трансформатора постов.
01:41:25Точно.
01:41:27Окей.
01:41:28И потом мы можем просто
01:41:29отрендерить их здесь.
01:41:30Это не слишком сложно.
01:41:32Понял.
01:41:35Окей.
01:41:36Теперь снова,
01:41:36официальный туториал здесь
01:41:38использует Edge view.
01:41:39Так что
01:41:39я использую Inertia.
01:41:40И,
01:41:41как вы видите,
01:41:41это просто приложение React
01:41:43в конечном счете,
01:41:44где мы также
01:41:46трансформируем и
01:41:46отправляем наши
01:41:48пропсы.
01:41:50Окей.
01:41:53Отображение одного
01:41:54поста.
01:41:55Да.
01:41:55Конечно.
01:41:55Так что теперь
01:41:56мы можем добавить
01:41:56еще один
01:41:58метод здесь,
01:42:00в наш
01:42:00контроллер.
01:42:01Потому что
01:42:02в наш
01:42:02пост
01:42:03контроллер
01:42:03на данный момент
01:42:04у нас есть один
01:42:05метод index
01:42:05для
01:42:05отображения
01:42:06всех постов.
01:42:07Но теперь
01:42:08мы хотим
01:42:08также
01:42:08добавить метод
01:42:09для
01:42:09отображения
01:42:10одного
01:42:10поста.
01:42:10Так что
01:42:11мы добавляем
01:42:11метод show
01:42:12здесь,
01:42:12как кажется.
01:42:12И опять же,
01:42:13эти имена
01:42:14зависят от вас.
01:42:14И позже,
01:42:16когда вы соедините
01:42:16их
01:42:17в файле маршрутов,
01:42:18вы
01:42:18должны убедиться,
01:42:19что они совпадают.
01:42:19Но мы увидим
01:42:19это через секунду.
01:42:20Так что здесь
01:42:20мы получаем параметры,
01:42:21потому что теперь
01:42:21у нас есть
01:42:23динамический маршрут.
01:42:23И опять же,
01:42:24вы можете знать это
01:42:25из React
01:42:25или еще откуда.
01:42:26Это маршруты
01:42:26с двоеточием.
01:42:26Параметры
01:42:27в имени маршрута,
01:42:28например,
01:42:28или знаки доллара
01:42:28в имени файла.
01:42:29Так что здесь
01:42:29мы также получаем
01:42:30динамические параметры,
01:42:30и мы увидим,
01:42:31как мы зарегистрируем
01:42:31эти маршруты
01:42:32через секунду.
01:42:32А затем
01:42:33мы ожидаем,
01:42:33что у нас будет
01:42:34параметр ID.
01:42:34Так что мы ищем
01:42:35пост с конкретным
01:42:35ID.
01:42:35Мы хотим
01:42:36вернуть ошибку,
01:42:37если мы не
01:42:38найдем его.
01:42:38Так что мы можем
01:42:39показать ошибку 404
01:42:39или любую другую ошибку.
01:42:40Я полагаю,
01:42:40мы хотим
01:42:41отрендерить
01:42:42вместо вьюхи.
01:42:43Мы хотим
01:42:43отрендерить...
01:42:44Мы хотим
01:42:44получить
01:42:45Inertia здесь,
01:42:46и мы повторно используем
01:42:46наш трансформатор
01:42:46постов,
01:42:47чтобы передать
01:42:48наш пост
01:42:49в...
01:42:49...
01:42:50...
01:42:50...
01:42:51чтобы мы могли
01:42:52показать ошибку 404
01:42:53или любую другую ошибку.
01:42:54...
01:42:55...
01:42:55...
01:42:57...
01:42:58...
01:42:58...
01:42:59отрендерить.
01:43:05Мы хотим
01:43:05получить
01:43:06Inertia здесь.
01:43:09И мы повторно используем
01:43:10наш трансформер
01:43:11постов,
01:43:12чтобы передать
01:43:13наш пост
01:43:14в
01:43:17компонент отображения,
01:43:18например.
01:43:18Так что,
01:43:19сейчас
01:43:20в папке
01:43:20Inertia,
01:43:21в папке
01:43:21post,
01:43:22нам нужно
01:43:22создать
01:43:23show.tsx
01:43:23или
01:43:24detail.tsx,
01:43:24или
01:43:25что-то
01:43:26вроде этого.
01:43:26И
01:43:26теперь
01:43:27там
01:43:28у нас
01:43:29есть
01:43:29наш
01:43:31пост-компонент.
01:43:35На самом деле,
01:43:35давайте назовем его
01:43:35Post.
01:43:36Вот так.
01:43:36И затем,
01:43:38как и раньше,
01:43:40я быстро
01:43:42украду это.
01:43:45Мы получаем
01:43:47Вот так.
01:43:48А затем.
01:43:49Как и раньше.
01:43:50Я.
01:43:50Быстро.
01:43:51Украду это.
01:43:55У нас получается.
01:43:55Один пост.
01:43:56Здесь.
01:43:56Без массива.
01:44:00Выберите это.
01:44:01А затем.
01:44:01Мы можем.
01:44:02Вернуть.
01:44:05Да.
01:44:05Конечно.
01:44:06Заголовок.
01:44:06Поста.
01:44:07Вот так.
01:44:11Привет.
01:44:12Да.
01:44:12Вот так.
01:44:13Хорошо.
01:44:16Что мы тут делаем?
01:44:17Итак.
01:44:19А затем.
01:44:19Конечно.
01:44:19Также.
01:44:20И...
01:44:21Краткое.
01:44:21Содержание поста.
01:44:21Например.
01:44:22Конечно.
01:44:23Хорошо.
01:44:23Итак, мы получили это.
01:44:24Э-э.
01:44:25Должно работать.
01:44:26Теперь.
01:44:27Нам нужно зарегистрировать его.
01:44:28В папке маршрутов.
01:44:30Итак, теперь.
01:44:30Мы можем добавить новый.
01:44:31Ой.
01:44:32Get-маршрут.
01:44:33Для слэша.
01:44:34Для слэша.
01:44:35Posts.
01:44:35А затем.
01:44:36Я полагаю.
01:44:37Что именно так мы регистрируем.
01:44:38Динамические маршруты.
01:44:39Давайте посмотрим.
01:44:41Да.
01:44:42С двоеточием ID.
01:44:44Вполне типично.
01:44:45А теперь.
01:44:46Мы говорим.
01:44:46Эй.
01:44:47В нашем контроллере постов.
01:44:48Это метод show.
01:44:49Который нас интересует.
01:44:51Потому что.
01:44:52В этом контроллере.
01:44:53Мы назвали этот метод.
01:44:54Show.
01:44:54Если вы выберете другое имя здесь.
01:44:56Нам придется выбрать другое имя и здесь тоже.
01:44:58Но show — это имя, которое я использую.
01:44:59Так что это должно работать.
01:45:02Итак.
01:45:05Какие ссылки у нас здесь есть?
01:45:08О.
01:45:08Это не ссылка на страницу с подробностями.
01:45:10Но если я добавлю posts 1.
01:45:13Да.
01:45:14Я загружаю.
01:45:15Стилизация полностью неверна.
01:45:16Но здесь, в самом низу.
01:45:17Мы можем увидеть.
01:45:18Контент.
01:45:19Итак.
01:45:20И.
01:45:21Заголовок.
01:45:22Markdown-движок для блога.
01:45:24Тоже здесь.
01:45:25Так что стилизация совсем нарушена.
01:45:26Но.
01:45:27Это работает.
01:45:28Мы видим этот маршрут.
01:45:31И мы, конечно, могли бы исправить стили.
01:45:32Но сейчас это не самое важное.
01:45:35Так что да.
01:45:36Мы получили вид.
01:45:37У нас уже есть все это.
01:45:39Используя именованные маршруты.
01:45:40О, это интересно.
01:45:40Да.
01:45:41Прямо сейчас мы жестко прописываем URL-адреса.
01:45:44И я на самом деле вообще не настраиваю никаких ссылок.
01:45:47Так что.
01:45:49Когда вы используете контроллер в определении маршрута.
01:45:51Adonis.js автоматически генерирует имя маршрута.
01:45:54Основанное на именах контроллера и метода.
01:45:56Так что, если у нас есть controllers.posts.index.
01:45:58Это.
01:45:59Получает имя posts.index автоматически.
01:46:02Так что я полагаю, мы могли бы перейти к...
01:46:05Странице index постов, где у нас есть все эти посты.
01:46:08И вместо использования тега привязки, вот так.
01:46:11Мы могли бы использовать.
01:46:12Компонент Link.
01:46:13Который идет из Inertia.js React.
01:46:17Также здесь.
01:46:18И тогда я не уверен.
01:46:19Есть ли у него проп to.
01:46:21Или это.
01:46:21Или ref.
01:46:23И тогда мы могли бы сказать что-то вроде.
01:46:26Routes.
01:46:29Posts.show.
01:46:34Похоже, так не работает.
01:46:42Posts.show.
01:46:49Да.
01:46:49Я использую другой подход.
01:46:50Я хочу использовать этот компонент Link.
01:46:53Снова.
01:46:55Есть ли он у нас где-нибудь здесь?
01:46:57Маршрут ссылки.
01:46:59О, хорошо.
01:46:59Это просто.
01:47:01Хорошо.
01:47:02Так что это link.
01:47:04Route.
01:47:08Почему я получаю ошибку здесь для маршрута?
01:47:11Создание ссылок.
01:47:12Компонент Link создает навигационные ссылки.
01:47:14О.
01:47:15Импорт неверный.
01:47:16Мне нужно импортировать это из.
01:47:20Здесь.
01:47:20Из пакета Adonis.
01:47:22Теперь у нас есть поддержка маршрута.
01:47:24Теперь это просто posts.
01:47:33Это просто строка.
01:47:34Это просто строка.
01:47:35Хорошо.
01:47:35Так что это просто.
01:47:37Route.
01:47:38Хорошо.
01:47:38Теперь мы получаем автодополнение здесь.
01:47:40А теперь мне нужно установить параметры.
01:47:43Параметры маршрута.
01:47:45Posts.id.
01:47:48Нет.
01:47:49Post.id.
01:47:53Так что это должен быть объект.
01:47:57Id установлено в post.id.
01:48:00И это теперь будет динамически генерировать другой маршрут для каждого поста.
01:48:03И подставит в этот динамический плейсхолдер ID поста, полагаю.
01:48:07Так что, если я сейчас перезагружу здесь.
01:48:09Не здесь.
01:48:10А здесь.
01:48:14Почему это не обновилось?
01:48:16Нужно ли мне перезапустить сервер разработки?
01:48:20О.
01:48:21Сохранение файла, вероятно, тоже поможет.
01:48:24Да.
01:48:24Теперь я могу нажать здесь и перейти к этим постам.
01:48:28Стилизация, конечно, всё ещё ужасная.
01:48:30Но это работает.
01:48:33И, конечно.
01:48:34Преимущество использования именованных маршрутов в том, что если мы когда-нибудь изменим путь,
01:48:38нам не придётся менять ссылки.
01:48:40Пока само имя маршрута не изменилось.
01:48:42Так что это, конечно, удобно.
01:48:44Итак.
01:48:45Вы можете не так уж часто менять путь.
01:48:47Но всё же.
01:48:48Довольно мило.
01:48:52Привет.
01:48:52Это Китти.
01:48:53И да.
01:48:55Это вдохновлено Laravel.
01:48:57Абсолютно.
01:48:58Думаю, они сами позиционируют себя как Laravel для JavaScript.
01:49:07Тебе приходится писать код вручную?
01:49:09Это как детская игрушка.
01:49:12Ну.
01:49:17Итак.
01:49:18Когда ты что-то изучаешь.
01:49:19Я бы определённо делал это.
01:49:21Я бы определённо писал код вручную.
01:49:23Потому что просто читая...
01:49:26Я бы делал и то, и другое.
01:49:28Но, конечно, для стрима.
01:49:29Я не нахожу это слишком интересным.
01:49:30Если я просто позволю ИИ прогнать всё это.
01:49:33Хотя я использовал его пару минут назад.
01:49:36Но да.
01:49:37Для обучения нужно определённо.
01:49:39Вникать в это.
01:49:40А одного чтения.
01:49:44Одного чтения недостаточно, чтобы хорошо усвоить материал.
01:49:46Теперь.
01:49:47Я не скажу, что ты будешь писать весь код.
01:49:50Как ты, может быть, делал четыре года назад.
01:49:52Даже близко не так.
01:49:54Но хотя бы основы.
01:49:56Чтобы почувствовать это.
01:49:56Я имею в виду здесь.
01:49:57Ты только что присоединился, верно.
01:49:58Но я просто копировал.
01:49:59То, что я написал, в основном нет.
01:50:01Мм.
01:50:03Код.
01:50:03Да.
01:50:03Да.
01:50:03Я знаю.
01:50:04Я тебя понял.
01:50:05Никаких обид.
01:50:06Просто.
01:50:07Я думаю, написание кода.
01:50:09Это в целом хороший аргумент.
01:50:10Вот почему я просто комментирую это.
01:50:12Думаю.
01:50:14Написание кода всё ещё полезно для обучения.
01:50:18Но.
01:50:19Хотя это была шутка.
01:50:21Или цитата.
01:50:24Это.
01:50:26Это.
01:50:26Это очевидно меняется.
01:50:28И меня спрашивали ранее.
01:50:32О новых курсах.
01:50:33И одна проблема.
01:50:34Или то, что я пытаюсь понять.
01:50:35Это как вы.
01:50:37Лучше всего изучаете технологии прямо сейчас.
01:50:41И имеет ли это всё ещё значение.
01:50:42И я бы сказал да.
01:50:43Это определённо всё ещё имеет значение.
01:50:45Но да.
01:50:46Именно этот момент.
01:50:47Сколько вы пишете от руки?
01:50:48Сколько копируете?
01:50:50Сколько позволяете ИИ объяснить или сгенерировать?
01:50:52Это.
01:50:53Я просто разглагольствую.
01:50:54Я просто разглагольствую.
01:50:54Но это определённо то, что меняется.
01:50:57А это Adonis JS.
01:51:00Так что.
01:51:00Это, по сути, Laravel для JavaScript.
01:51:09Хорошо.
01:51:09Так что.
01:51:14Да.
01:51:15Комментарии.
01:51:16Не думаю, что я буду это делать.
01:51:18А мне нужно уходить через 10 минут.
01:51:20Так что, вероятно, оставим всё как есть.
01:51:22И просто бегло взглянем на оставшиеся несколько.
01:51:28Страниц здесь.
01:51:29В этом руководстве всё равно осталось немного.
01:51:31Так что мы прошли его довольно хорошо.
01:51:33Формы и валидация.
01:51:35Итак, идея здесь в том.
01:51:37Что, конечно, у нас также могут быть методы контроллера.
01:51:40Методы контроллера, которые вызываются.
01:51:43При POST-запросах.
01:51:45И мы можем увидеть это в.
01:51:48У нас нет контроллера пользователя?
01:51:52Пользователь.
01:51:54Этот.
01:51:54Контроллер новой учётной записи.
01:51:56Здесь.
01:51:57Store.
01:51:57Это.
01:51:59Метод контроллера.
01:52:00Который вызывается.
01:52:02При POST-запросе.
01:52:04Вот этот.
01:52:05И.
01:52:06Поэтому.
01:52:07Это просто обычный метод.
01:52:08Но там мы уже можем увидеть.
01:52:10Вы можете использовать validate using.
01:52:13Метод.
01:52:13И определить валидатор.
01:52:14Который в конце.
01:52:16Просто небольшой служебный объект.
01:52:18Созданный с помощью этого инструмента vine.
01:52:21Где вы можете определить некоторые правила.
01:52:22Для того, какие данные вы хотите принимать.
01:52:24А затем.
01:52:24Ошибки будут генерироваться автоматически.
01:52:26Для вас, если.
01:52:27Если критерии валидации не соблюдены.
01:52:29Так что вся идея.
01:52:30Стоящая за Laravel.
01:52:30И Adonis.
01:52:31Заключается в том, что они делают много работы за вас.
01:52:33И вы можете.
01:52:33Определить свою логику.
01:52:34На довольно высоком уровне.
01:52:36В то время как.
01:52:37В Next.
01:52:37JS.
01:52:37И так далее.
01:52:38Вам часто приходится становиться очень специфичным.
01:52:41И, очевидно.
01:52:41Вам нужно принести свою собственную библиотеку валидации.
01:52:43И всё такое веселое.
01:52:52Итак, что мы здесь делаем.
01:52:54Так это регистрируем маршруты.
01:52:56Мы это уже видели.
01:52:59Создание нового представления в этом случае.
01:53:00И здесь они создают форму.
01:53:02Ну, это всё некоторые специфичные для Edge.
01:53:05Фрагменты кода.
01:53:06Но, конечно.
01:53:08У нас это тоже есть.
01:53:12Где это?
01:53:13Войти.
01:53:14Да.
01:53:14Мы можем увидеть это, если используем inertia.
01:53:17У нас есть этот компонент формы здесь.
01:53:19Который исходит из пакета Adonis.js inertia.
01:53:22Который также связан с маршрутом.
01:53:24Который должен быть запущен.
01:53:25Если форма отправлена.
01:53:26Это тот маршрут store.
01:53:27Мы только что видели.
01:53:28Или это действие контроллера store.
01:53:30Которое, в конце концов.
01:53:31Вызывается этим маршрутом.
01:53:33И данные.
01:53:34Я полагаю, упакованы.
01:53:36В запрос.
01:53:37И автоматически отправлены на бэкенд.
01:53:39Что, конечно, удобно.
01:53:40Что вам не нужно писать код для этого самим.
01:53:42Или просить ИИ написать его для вас.
01:53:45Если вы используете Edge.
01:53:46Вы можете рендерить поля формы вот так.
01:53:48И, возможно.
01:53:50Об этом немного легче рассуждать.
01:53:51И читать, я бы сказал.
01:53:56А затем мы можем создавать валидаторы.
01:53:57Мы видели один до этого.
01:53:58С этой штукой vine.
01:54:00Где вы просто определяете.
01:54:01Для данных.
01:54:02Которые собираетесь получить.
01:54:04Каковы ваши правила.
01:54:05Итак, минимальная длина.
01:54:06Максимальная длина.
01:54:07Тип данных.
01:54:08И так далее.
01:54:10Берем метод store.
01:54:11И снова.
01:54:11Мы можем использовать ORM.
01:54:13Использовать наш класс.
01:54:14Вызвать статический метод create.
01:54:16Чтобы сохранить данные.
01:54:19Комментарии.
01:54:20Делаем то же самое.
01:54:23Также связываем с пользователем.
01:54:24Через ID.
01:54:26И мы получаем пользователя.
01:54:28Через этот auth.
01:54:30Свойство.
01:54:31Которое мы получаем автоматически.
01:54:32И опять же.
01:54:33Это как.
01:54:33Adonis делает свое дело.
01:54:35И выполняет аутентификацию за вас.
01:54:37Благодаря middleware.
01:54:39Который зарегистрирован.
01:54:40Верно.
01:54:40Так что в роутах.
01:54:40У нас есть некий.
01:54:41Auth-middleware.
01:54:42Например.
01:54:43И любые маршруты здесь.
01:54:44Требуют аутентификации.
01:54:46И любые маршруты там.
01:54:48Следовательно.
01:54:48Тоже.
01:54:51Также получаем это auth.
01:54:53Свойство.
01:54:54Которое вы можете использовать.
01:54:55Чтобы получить данные.
01:54:56О текущем.
01:54:57Аутентифицированном пользователе.
01:54:58Или которое вы можете использовать.
01:54:59Чтобы выйти из системы.
01:55:00Как в этом случае.
01:55:01И так далее.
01:55:02Так что это все.
01:55:03Довольно удобно.
01:55:04Как только настроено.
01:55:06Я по крайней мере полагаю.
01:55:07Это не то что.
01:55:08Я работал с этим раньше.
01:55:09Но да.
01:55:11Я узнал.
01:55:11View 3 от вас.
01:55:12И передал принципы.
01:55:14В кодеки.
01:55:14Такие как кодеки.
01:55:15Пишет высокого качества.
01:55:16Так что ваши уроки.
01:55:16Все еще ценны.
01:55:17Для хорошего промптинга.
01:55:18Да.
01:55:18И одна вещь, которую я изучаю.
01:55:20Это также.
01:55:20Как вы можете.
01:55:22Для будущих курсов.
01:55:23Включать материалы.
01:55:24Вроде навыков агентов.
01:55:25Или дополнительные документы.
01:55:26Которые вы можете скармливать.
01:55:27Своим агентам.
01:55:28Чтобы помочь им.
01:55:31Писать лучший код.
01:55:32Хотя, конечно.
01:55:33Это никогда не будет гарантией.
01:55:34Потому что агенты.
01:55:37Всегда могут делать.
01:55:38Что-то свое.
01:55:39И так далее.
01:55:40Но это то.
01:55:40Что я также изучаю.
01:55:41Конечно.
01:55:42И что я предпочитаю.
01:55:43Adonis или Vue 3.
01:55:45Так вот, Adonis.
01:55:46Я только.
01:55:47Начал с ним работать.
01:55:48Я вообще не использовал его.
01:55:49Раньше.
01:55:50И Vue 3.
01:55:52Не совсем.
01:55:52Альтернатива.
01:55:53Потому что Adonis.
01:55:54Это полный стек.
01:55:55А Vue.
01:55:55Это клиентская часть.
01:55:57Фронтенд.
01:55:58С Nuxt.
01:55:59Это был бы снова полный стек.
01:56:00Опять же.
01:56:00Но тогда.
01:56:01У нас все равно были бы.
01:56:02Разные философии.
01:56:03Где Adonis.
01:56:04Это все включено.
01:56:06Так что.
01:56:06Всё это.
01:56:07Например, аутентификация.
01:56:08Там уже встроена.
01:56:09Тогда как в Nuxt.
01:56:11Ну, как и.
01:56:11Как и с Next.
01:56:12Нужно приносить.
01:56:13Свои.
01:56:14Библиотеки.
01:56:15И в конечном итоге.
01:56:16Я не знаю.
01:56:17Что я предпочитаю.
01:56:17Мне нравится.
01:56:18Подход Adonis.
01:56:19И я определенно.
01:56:21Вижу в этом.
01:56:22Ценность.
01:56:23Если вы строите.
01:56:25Full-stack.
01:56:27Приложение.
01:56:28Хотя.
01:56:28Я.
01:56:29Так привык.
01:56:30К Next.
01:56:31JS.
01:56:31К стеку.
01:56:32Начинать с ним.
01:56:33И всё такое.
01:56:34Что я.
01:56:35Не знаю.
01:56:36Стоит ли переходить.
01:56:37На Adonis.
01:56:37Просто потому что.
01:56:38Я, наверное.
01:56:39Быстрее.
01:56:40С теми.
01:56:41Другими.
01:56:41Технологиями.
01:56:43Но.
01:56:44С другой стороны.
01:56:45Есть веские причины.
01:56:46Например.
01:56:46Иметь.
01:56:47Меньше.
01:56:48Внешних.
01:56:49Зависимостей.
01:56:50Помимо самого Adonis.
01:56:51И так далее.
01:56:51Так что.
01:56:52Я, наверное, буду.
01:56:53Продолжать.
01:56:54Играться с этим.
01:56:55И затем.
01:56:55Оценить.
01:56:56Где это полезно.
01:56:57Для меня.
01:56:58Где это не так.
01:56:58Если я захочу больше строить.
01:57:00На нём.
01:57:02Да.
01:57:03Это.
01:57:03Это, по сути.
01:57:04План.
01:57:05И я думаю.
01:57:07Ну.
01:57:07Нет.
01:57:08Нет, не буду.
01:57:08И всё же.
01:57:09Меня не особо волнует.
01:57:10Стилизация.
01:57:10Это просто CSS.
01:57:12А вот авторизация.
01:57:13Я хочу на это взглянуть.
01:57:16Так что есть ещё пакет.
01:57:18Который можно установить.
01:57:19Он часть экосистемы.
01:57:20Adonis.
01:57:21Пакет для балансировки.
01:57:22Который нужен для.
01:57:24Нахождения имени.
01:57:25И название этой главы.
01:57:27Я бы сказал.
01:57:27Это.
01:57:28Это отвечает.
01:57:29За блокировку людей.
01:57:30Которым не разрешено.
01:57:31Что-то делать.
01:57:33И, конечно.
01:57:35Авторизация.
01:57:36В отличие от аутентификации.
01:57:37Это про то.
01:57:39Чтобы блокировать пользователей.
01:57:40От выполнения определенных вещей.
01:57:41Которые они не должны.
01:57:42Делать.
01:57:43Так, например.
01:57:44Пользователь может войти в систему.
01:57:46Но, конечно.
01:57:46Он не должен.
01:57:47редактировать чужие записи.
01:57:48Другого пользователя.
01:57:49Логично.
01:57:51Так что.
01:57:52Одной аутентификации
01:57:52недостаточно.
01:57:53Часто вам нужна
01:57:54авторизация.
01:57:55В дополнение.
01:57:57И вот здесь
01:57:57пакет Bouncer
01:57:58кажется полезным.
01:58:01Потому что тогда
01:58:01вы можете создавать
01:58:02так называемые политики,
01:58:03как кажется.
01:58:04Давайте взглянем.
01:58:05Политика — это класс,
01:58:07который расширяет
01:58:07класс
01:58:08из Adonis,
01:58:09из пакета Bouncer
01:58:10вот здесь.
01:58:11И мы можем определить.
01:58:13Окей.
01:58:13Мы можем, по сути,
01:58:15определить права доступа здесь.
01:58:16Например,
01:58:17редактирование разрешено,
01:58:18если ID пользователя
01:58:20совпадает с ID,
01:58:21которому принадлежит
01:58:22этот пост,
01:58:23который мы пытаемся отредактировать.
01:58:24То же самое для удаления.
01:58:26И тогда мы, вероятно,
01:58:27сможем применить эти политики.
01:58:29Давайте посмотрим.
01:58:30Мы...
01:58:30У нас они есть.
01:58:34Добавить методы контроллера.
01:58:43Где мы применяем?
01:58:44А, точно.
01:58:45Вот здесь.
01:58:45Так что,
01:58:46в нашем контроллере...
01:58:48Мы...
01:58:48Вот здесь.
01:58:49Они добавили новый метод,
01:58:50метод редактирования,
01:58:51который должен запускаться,
01:58:52очевидно,
01:58:52если вы...
01:58:53пытаетесь отправить форму,
01:58:54в которой хотите отредактировать пост,
01:58:56или где вы...
01:58:57вероятно, хотите загрузить страницу
01:58:58для редактирования поста здесь.
01:58:59Теперь, когда я смотрю на это,
01:59:01и в этом методе мы...
01:59:02находим
01:59:03пост,
01:59:04который хотите редактировать,
01:59:05но затем,
01:59:06прежде чем вернуть представление,
01:59:08этот пакет Bouncer
01:59:09дает нам такую штуку,
01:59:11где мы загружаем
01:59:12политику,
01:59:13которую хотим применить,
01:59:14и где мы, по сути,
01:59:15проверяем через эту политику,
01:59:16имеет ли пользователь,
01:59:17который пытается это редактировать,
01:59:19на это право.
01:59:23Логично.
01:59:25Окей.
01:59:27Так, давайте посмотрим.
01:59:29Чат.
01:59:30ИИ может построить приложение
01:59:31десятью разными способами
01:59:32в одной и той же библиотеке,
01:59:33так что, может, стоит сосредоточиться на
01:59:34парадигмах программирования,
01:59:35на том, как организовывать код.
01:59:37Да.
01:59:38Абсолютно.
01:59:38Я думаю, что
01:59:39это важные навыки
01:59:41как для разработчиков,
01:59:42так и для ИИ.
01:59:44Через документацию,
01:59:45через навыки,
01:59:46которые вы преподаете,
01:59:47на определенных шаблонах,
01:59:48которые вы знаете,
01:59:49ваши основы
01:59:50и тому подобное.
01:59:51И именно поэтому
01:59:52я также планирую
01:59:53курсы по основам программирования,
01:59:54основам систем,
01:59:55проектированию систем
01:59:55и всему такому интересному.
01:59:57Когда есть вариант получше —
01:59:58создавать бэкенд веб-API
02:00:00на строго типизированных языках,
02:00:01таких как C#.
02:00:02И...
02:00:03не уверен,
02:00:03почему здесь было цензурирование,
02:00:05или полагаться на Node.js
02:00:06с TypeScript,
02:00:07в котором типы стираются,
02:00:08и существует куча уязвимостей
02:00:09в NPM-пакетах.
02:00:12В конечном счете,
02:00:13что касается бэкенд-языков,
02:00:15я мог бы говорить час
02:00:16только об этом,
02:00:17а у меня нет часа.
02:00:18Но...
02:00:20огромное преимущество
02:00:21Node.js
02:00:22и всей экосистемы JavaScript
02:00:23заключается,
02:00:24конечно, в том,
02:00:24что ИИ очень хорошо ее знает.
02:00:26Если вы планируете использовать ИИ
02:00:28для разработки,
02:00:28то здесь есть масса пакетов,
02:00:30но, конечно,
02:00:31существует огромный минус
02:00:32в виде атак на цепочки поставок
02:00:33и так далее.
02:00:34Безусловно.
02:00:35И другие языки
02:00:36тоже могут обеспечить лучшую производительность.
02:00:38Я бы обязательно
02:00:39рассмотрел использование
02:00:41Go,
02:00:41Rust,
02:00:42C#,
02:00:42всё, что вам интересно
02:00:44для бэкенд-разработки.
02:00:45Но я скажу,
02:00:46что мой опыт
02:00:47показывает,
02:00:48что у вас высокая скорость,
02:00:49когда вы используете
02:00:50TypeScript,
02:00:51потому что с ИИ...
02:00:52он...
02:00:53он знает его так хорошо.
02:00:55И, конечно,
02:00:56лично я
02:00:56знаю его очень хорошо,
02:00:57так что
02:00:58я могу быстро заметить части,
02:00:59где ИИ
02:01:01выбирает неверное направление
02:01:02и так далее.
02:01:02Так что,
02:01:04это есть.
02:01:05Но...
02:01:06да.
02:01:06Безусловно,
02:01:06в использовании
02:01:07других языков
02:01:08для бэкенда
02:01:09есть много достоинств.
02:01:10Совсем не обязательно
02:01:11использовать JavaScript для всего.
02:01:12Почему NestJS популярнее?
02:01:14Честно говоря, не знаю.
02:01:16Я никогда до конца не понимал,
02:01:17почему же Adonis...
02:01:19Почему он...
02:01:19остается
02:01:22такой нишевым.
02:01:23У меня
02:01:24нет
02:01:24внятного
02:01:25объяснения этому.
02:01:26Но...
02:01:28я...
02:01:29должен идти.
02:01:30Это было интересно.
02:01:31Это было весело.
02:01:32Определенно интересно
02:01:32было погрузиться в Adonis
02:01:34и взглянуть на него.
02:01:35Надеюсь, вам тоже понравилось.
02:01:36Спасибо, что присоединились.
02:01:37Снова.
02:01:39Я стараюсь возвращаться
02:01:40каждый четверг.
02:01:40На следующей неделе
02:01:41у меня не получится.
02:01:42А вот через неделю
02:01:43посмотрим.
02:01:45Но да,
02:01:46я всегда анонсирую это
02:01:47в своем Discord.
02:01:48Так что, если вы еще
02:01:48не там,
02:01:49можете зайти на
02:01:50[akadamind.com/community](https://www.google.com/search?q=https://akadamind.com/community),
02:01:51вступить в Discord.
02:01:51Я анонсирую там.
02:01:53Или, конечно,
02:01:54просто подпишитесь,
02:01:54следите за мной,
02:01:56и тогда вы увидите.
02:01:56Но, в общем,
02:01:57четверг,
02:01:5817:00
02:01:59по центральноевропейскому
02:02:00летнему времени.
02:02:01И я обычно заканчиваю
02:02:03в то время,
02:02:04в которое заканчиваю сейчас.
02:02:05И да, спасибо всем.
02:02:06Хорошего вам дня,
02:02:07вечера,
02:02:09утра,
02:02:09смотря что у вас сейчас.
02:02:11Надеюсь, увидимся в будущем.
02:02:13И да,
02:02:13спасибо
02:02:14всем за то, что были с нами.
02:02:15...
02:02:17...
02:02:17...

Key Takeaway

Adonis.js предлагает JavaScript-разработчикам целостный, фулстек-фреймворк с предсказуемой архитектурой и встроенными инструментами безопасности, минимизируя необходимость интеграции разрозненных зависимостей.

Highlights

  • Adonis.js представляет собой полноценный JavaScript-фреймворк с «батарейками в комплекте», включающий встроенную аутентификацию, собственный ORM (Lucid) и валидатор, что снижает зависимость от сторонних библиотек.

  • Фреймворк поддерживает три архитектурных подхода к фронтенду: серверный рендеринг HTML с использованием шаблонизатора Edge, интеграцию с React через Inertia.js или создание чистого REST API.

  • Архитектура Adonis.js основана на классическом паттерне MVC (Model-View-Controller) и использует файлы миграций для управления схемой базы данных, отделяя определение структуры данных от бизнес-логики моделей.

  • Использование именованных маршрутов позволяет централизованно управлять ссылками: при изменении пути в файле конфигурации они автоматически обновляются во всем приложении.

  • Пакет Bouncer в экосистеме Adonis.js обеспечивает авторизацию на основе политик, позволяя декларативно ограничивать доступ к методам контроллера в зависимости от прав пользователя.

Timeline

Философия и архитектура Adonis.js

  • Adonis.js является JavaScript-аналогом PHP-фреймворка Laravel.
  • Фреймворк предоставляет встроенную аутентификацию, кэширование и ORM.
  • Поддерживаются три подхода: Hypermedia (шаблонизатор Edge), Inertia.js (React/Vue) и REST API.

Фреймворк нацелен на предоставление всех необходимых инструментов в одном пакете, что снижает риски, связанные с атаками на цепочки поставок при использовании множества мелких зависимостей. Архитектура поддерживает как традиционный рендеринг на стороне сервера, так и современные гибридные решения через Inertia.js.

Настройка окружения и структура проекта

  • Проект использует SQLite по умолчанию для быстрой и легкой разработки.
  • Файлы конфигурации разделены на настройки приложения (config), секреты окружения (.env) и конфигурацию фреймворка (adonisrc.ts).
  • Папка resources содержит шаблоны Edge и фронтенд-активы, а start отвечает за загрузку жизненного цикла приложения.

Структура проекта четко разделяет доменную логику (app), конфигурацию (config) и файлы запуска (start). Для работы с базой данных используется Lucid ORM, а для управления фронтенд-ресурсами интегрирован Vite.

Работа с базой данных и моделями

  • Миграции используются для создания схемы базы данных, а модели — для программного взаимодействия с данными.
  • Связи между моделями (один-ко-многим) настраиваются с помощью декораторов в классах моделей.
  • Фабрики (factories) позволяют генерировать фиктивные данные для разработки, а сидеры (seeders) наполняют ими базу данных.

Взаимодействие с данными происходит через Lucid ORM, где таблицы описываются как классы моделей. Связи между объектами (например, пользователи, посты и комментарии) задаются декларативно, что упрощает управление сложными запросами без написания необработанного SQL.

Контроллеры, роутинг и авторизация

  • Контроллеры получают HTTP-контекст, содержащий данные запроса, объект ответа и инструменты аутентификации.
  • Именованные маршруты автоматически генерируются на основе имен контроллера и метода, обеспечивая удобное управление ссылками.
  • Пакет Bouncer позволяет применять политики доступа (policies) для проверки прав пользователей перед выполнением операций.

Разработка логики приложения строится на методах контроллера, которые обрабатывают запросы и взаимодействуют с ORM. Авторизация реализуется через создание классов политик, проверяющих принадлежность ресурсов пользователю, что обеспечивает безопасность на уровне бизнес-логики.

Community Posts

No posts yet. Be the first to write about this video!

Write about this video