Обновить
64K+

Node.JS *

Среда для запуска JavaScript-приложений

78,44
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

Claude Code — Все статуслайны показывают тебя. Я сделал тот, который показывает других

Уровень сложностиПростой
Время на прочтение6 мин
Охват и читатели9.1K

В два часа ночи ты упираешься в лимит модели. Сессия на середине, мысль на середине, и до сброса окна ещё полтора часа. Ты сидишь и смотришь в терминал, где написано, сколько ты потратил токенов, сколько это стоило в долларах и сколько процентов контекста съедено.

Чего там не написано — что прямо сейчас ещё шестеро сидят и ждут того же сброса. И четверо из них тоже глубоко за полночь.

Про это и получился инструмент. Одна строка в статуслайне Claude Code:

Читать далее

Новости

Я 22 месяца двигал ставки в Telegram Ads руками, потом написал автомат. Он воевал сам с собой

Уровень сложностиСредний
Время на прочтение14 мин
Охват и читатели5.9K

За 22 месяца в Telegram Ads у меня накопилось 1 043 канала, 3 000 креативов и стопка скриптов вокруг кабинета: харвест справочника, скоринг каналов языковой моделью, степпер ставок и гейт по прогнозной цене подписчика. В какой-то момент объём подписок просел на треть без видимой причины. Две недели я искал её снаружи, а нашёл внутри: степпер поднимал ставку объявлению без показов, гвард через сорок пять минут ронял её обратно, и оба скрипта писали в лог успех. Разбор с кодом, конечным автоматом и граблями, включая тихо непринятый PATCH и мёртвую зону на 250 показах.

Читать далее

V8 startup snapshot: как правильно запустить JS-код на сервере

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели7.1K

Представьте типичную ситуацию. У вас есть сервер на каком-то языке (сейчас какой именно для нас не важно, но допустим, это Rust). И в нём по каким-то причинам нужно исполнить JavaScript-код. Например, фронтенд написан на React, и вы хотите рендерить HTML на сервере (SSR). Или есть бизнес-логика, которая проще пишется на JS. Или библиотека, которая существует только в npm, и переписывать её на Rust нет ни сил, ни желания. Таких примеров можно привести множество: markdown, dompurify, highlight.js и т.д.

Читать далее

Один контракт данных, разные адаптеры: как перестать писать миграцию магазина заново

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели6.5K

Первый файл, который я получил при переезде своего магазина с InSales, парсер прочитал как одну длинную строку мусора. Выгрузка заказов оказалась в UTF-16 LE с BOM и табуляцией вместо запятой — ни один разумный дефолт не подошёл.

Тогда это выглядело как разовая неприятность: поправил чтение, написал скрипт, ночь работы, всё уехало, скрипт лёг в репозиторий. На следующем проекте он не переиспользовался — другая платформа, другие колонки, другие правила. На третьем стало видно, что повторяется почти вся работа: связать заказ с клиентом, не создать дублей, не потерять адреса страниц, уметь перезапуститься. Разное только на входе — кодировка, формат, названия колонок, единицы измерения.

Отсюда вывод, к которому стоит прийти раньше, чем на третьем проекте: середина должна быть одна, а платформенная специфика — жить в тонком слое на входе. Ниже — как этот каркас устроен у меня, с кодом из работающего проекта: собственного магазина, который я перевёз с InSales на свой движок на Next.js и PostgreSQL.

Сразу оговорюсь про доставленные миграции: полностью пройдена одна — та, о которой пойдёт речь. Про требования к адаптерам под 1С‑выгрузки и товароучётные API дальше я говорю как о проектных требованиях к каркасу; готовыми кейсами они не являются. Это важно, чтобы вы правильно оценили вес каждого утверждения.

Резонный вопрос до всего остального: почему не готовый инструмент. Airbyte, n8n, коннекторы к товароучётным системам делают ровно это — вытащить, преобразовать, положить. Для регулярной синхронизации они и есть правильный выбор. Разовая миграция магазина отличается тем, что сложность сидит не в перекладывании строк, а в доменных правилах: как собрать заказ из нескольких строк, что делать с позицией, товара которой больше нет в каталоге, как при повторном прогоне не затереть свежие данные старыми. Эти правила всё равно пишутся руками, а в визуальной цепочке трансформаций их неудобно тестировать и нельзя перезапустить кусочком. Поэтому середина своя, а тонкими остаются края.

Читать далее

Тест проходил за миллисекунды. На настоящем файле тот же код думал минуту

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели7.5K

«👋».length === 2 — это знают все. Дальше все пишут честную функцию, которая ходит по строке по символам, а не по кодовым единицам UTF-16. И почти всегда она получается квадратичной: и длина, и обращение по индексу проходят строку с начала, поэтому обычный цикл по ним — это n²/2 шагов без единого вложенного цикла в коде.

В тестах это невидимо. Десять тысяч символов обходятся за 70 миллисекунд, а строки в тестах короткие, потому что их пишут руками. Дефект жил у меня полгода под зелёными тестами и вылез, когда программа впервые прочитала настоящий файл в 300 килобайт: вместо секунды — минуты.

Внутри: замеры роста, починка через один вопрос «есть ли в строке суррогатная пара», и почему тест на время здесь бесполезен, а тест на показатель роста — нет.

Читать далее

Назад в машинный зал: как собрать эмулятор PDP-11/70 с телетайпом, блэкджеком и без Rust — где я схалтурил

Уровень сложностиСложный
Время на прочтение10 мин
Охват и читатели6.5K

Продолжение статьи «Назад в машинный зал: как собрать эмулятор PDP-11/70 с телетайпом, блэкджеком и без Rust» (первая часть). Первая часть — про то, что получилось; эта — про то, почему так, и во что это выйдет дальше.

Посмотреть на живую систему самостоятельно в браузере можно тут: https://amesk.github.io/yaPDP/pdp11.html

Читать далее

Из генерации — в переписку: доводим ответ ИИ‑агента до клиента и CRM на n8n

Уровень сложностиСредний
Время на прочтение13 мин
Охват и читатели9.5K

Всем привет!) Напомню: в первой статье я показал дебаунс на Redis, который склеивает дробные сообщения клиента. Во второй — модуль привязки «чат = сделка» и то, почему вебхуки стоит держать в изолированных ключах. Обе части заканчиваются примерно одинаково: «...и текст уходит ИИ‑агенту». Это, пожалуй, тот финал, на котором обычно ставят точку и заливают демо на GitHub... Но не в данном случае!)

Читать далее

Почему Deno быстрее Node.js: расследование

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели9.2K

На официальном сайте Deno (раздел Built for the real world) красуется любопытная табличка. Согласно их замерам, Deno уходит в отрыв от Node.js по HTTP аж в 1.65 раза:

Независимые тесты (denosaurs/bench, pkgpulse 2026, jsmanifest 2026) показывают похожую картину: Deno стабильно быстрее на HTTP-нагрузке. Я решил копнуть глубже и понять, где Deno получает преимущество по сравнению с Node.js.

Читать далее

Подмена страницы интернет-банка First Partner Bank на Standoff 365

Время на прочтение6 мин
Охват и читатели8.8K

Привет, Хабр! Будем знакомы — grizzzer, участник различных CTF-команд и независимый исследователь кибербезопасности. В этой статье разберу, как я реализовал критическое событие в банковском сегменте онлайн-полигона Standoff 365 — «Дефейс веб-сервиса ДБО First Partner Bank».

Покажу всю цепочку — от DNS-разведки до эксплуатации уязвимости server-side template injection (SSTI) в шаблонизаторе Pug и финальной подмены текста на главной странице.

Читать далее

IndexNow из Node.js: переобход без аккаунтов, и почему fetch обрывается там, где curl проходит

Время на прочтение6 мин
Охват и читатели6.2K

Чтобы сказать Яндексу «страница изменилась, приди посмотреть», аккаунт в Вебмастере не нужен. Есть протокол IndexNow: вы кладёте в корень сайта файл с ключом, шлёте POST со списком адресов — и поисковик приходит за часы вместо недель. Ни регистрации, ни OAuth, ни капчи. Реализуется тридцатью строками на Node.js без единой зависимости.

Ниже — рабочий скрипт целиком, шесть кодов ответа, которые он может получить, и три грабли, на которые я наступил, пока доводил его до состояния «запустил и забыл». Одна из них интереснее прочих: fetch в Node падает с fetch failed на том же запросе, который curl отправляет с первого раза.

Читать далее

Почему рекламный пост в Telegram нельзя публиковать через copyMessages

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели6.2K

Если бот копирует один и тот же пост в десять каналов, в Google Analytics все клики свалятся в одну кучу. URL у скрытой ссылки живёт не в тексте, а в MessageEntity, а copyMessages копирует его как есть. Ниже — как пересобрать пост под каждую площадку, не сломав жирный шрифт, эмодзи и health‑check.

Telegram умеет одно очень удобное действие: copyMessages. Берёте сообщение из чата A, кладёте в чат B — форматирование, медиа, альбом, скрытые ссылки, всё на месте. Для рассылок и зеркал это идеальный метод.

Для рекламы он ломает самое важное.

Рекламодатель покупает размещения в разных каналах и смотрит в свою аналитику: откуда пришёл клик. Если во всех десяти постах в text_link лежит один и тот же https://shop.example/sale, UTM бесполезен. Каналы неразличимы. Сделка неразличима. Дата размещения неразличима.

Как пересобрать пост и не убить UTM

410.chat — Одноразовый чат для двоих

Время на прочтение5 мин
Охват и читатели95K

Последние недели делал небольшой проект, который в итоге назвал 410.chat.

Идея довольно простая. Иногда нужно поговорить с человеком напрямую, но совершенно не хочется ради этого обмениваться тг, номером телефона, почтой или создавать какой-то постоянный контакт. Например, встретились где-нибудь в комментариях, на форуме, в сообществе или на площадке объявлений. Нужно на пять минут уйти в приватный разговор — и всё.

Обычно для этого мы всё равно идём в какой-нибудь мессенджер и фактически открываем другому человеку постоянный способ связаться с собой. Мне стало интересно сделать наоборот: контакт, который существует только пока идёт конкретный разговор.

Так появился 410.

Читать далее

Self‑hosted вместо подписок: асинхронная очередь для ИИ‑агента на n8n и Redis

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели6.5K

В прошлой статье я показал, как простой дебаунс на Redis спасает бюджет от дробных сообщений: клиент строчит «привет» — «сколько стоит» — «а есть другой размер» пятью сообщениями подряд, а LLM получает один склеенный промпт.

Читать далее

Ближайшие события

Заголовки товарной кампании Директа — это теги YML-фида: прослойка на Node вместо правки сайта

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели5.4K

Товарная кампания и смарт-баннеры Яндекс Директа не дают редактировать текст объявления в интерфейсе. Заголовок Директ берёт из тега <name> товарного фида, описание — из <description>, и оба тега писал сайт: под карточку товара, а не под рекламную ленту. В галерее видно около 35 знаков заголовка, жёсткий предел — 56, дальше Директ обрезает по символам. «Печеные яблоки, фаршированные медом и грецкими орехами» в объявлении выглядят как «Печеные яблоки, фаршированные медо».

Сайт при этом трогать нельзя: та же карточка ранжируется в поиске и стоит в чеке, у неё своя работа. Ниже — как мы вклинились между сайтом и Директом одним процессом на Node без базы данных, который хирургически подменяет ровно два тега в YML, зачем над генератором заголовков стоит валидатор с правилами модерации и человек на аппруве, и что из этого вышло за первые дни на реальном проекте: пекарня с доставкой по Москве, около пятисот позиций в фиде.

Текст пригодится, если у вас уже крутятся товарная кампания или смарт-баннеры на YML-фиде и заголовки в них выглядят как строки из накладной. Если товарных форматов ещё нет — эта статья про инженерную часть, не про запуск с нуля.

Читать далее

Управляемые корутины в TypeScript: как получить контроль над асинхронностью и памятью. Разбираемся во всех аспектах

Уровень сложностиСложный
Время на прочтение16 мин
Охват и читатели8.8K

Современный JavaScript / TypeScript сегодня, предоставляет мощный инструмент для асинхронного программирования, который знаком каждому - async/await на основе Promise. Он позволяет писать последовательный код и легко обрабатывать ошибки. Однако за простотой скрываются серьёзные ограничения, которые становятся критичными в высоко-нагруженных системах, играх, сложных пользовательских интерфейсах и приложениях, требующих предсказуемой производительности.

Представьте себе сервер, обрабатывающий тысячи запросов одновременно. Все они конкурируют за процессорное время. Как гарантировать, что запрос от клиента выполнится раньше, чем фоновая синхронизация? Как отменить долгую операцию, если клиент разорвал соединение? Как избежать пауз сборщика мусора при создании миллионов временных объектов? Нативный async/await не даёт ответов на эти вопросы - он лишь оборачивает асинхронные операции в удобный синтаксис.

В этой статье мы разберём, как кооперативные корутины (Coroutines) решают эти задачи на примере моей библиотеки ts-adaptive-coroutines, изучив каждый аспект по кирпичикам, посмотрев на инструмент, который добавляет в TypeScript адаптивные приоритеты, арены памяти, каналы, семафоры и много-поточность.

Читать далее

Назад в машинный зал: как собрать эмулятор PDP-11/70 с телетайпом, блэкджеком и без Rust

Уровень сложностиСложный
Время на прочтение11 мин
Охват и читатели12K

Кризис среднего возраста бывает разным: кто-то покупает спорткар, а я — собрал эмулятор PDP-11/70 с телетайпом, блэкджеком и без единой строки на Rust.

Зачем? Просто чтобы вспомнить, как пахнет машинный зал, и заодно проверить, не разучился ли я программировать. В итоге получился работающий иммерсивный эмулятор в браузере (и не только), который загружает операционки того времени.

В этой статье — рассказ о целях разработки, выборе движка, архитектуре и ограничениях, обёртке в Tauri для автономного запуска, автоматизации скриншотов и граблях, на которые я наступил.

Если вам тоже за 30, 40 (или 50), и вы скучаете по временам, когда «байт» был не просто словом, — заходите, будет ностальгически-познавательно.

Живой эмулятор в браузере — amesk.github.io/yaPDP (запускается в 2 клика за несколько секунд)
Исходный код и десктопная версия — https://github.com/amesk/yaPDP

Предупреждение: под катом много технических деталей, картинок, фрагментов кода и моих рассуждений вслух. Я не стал их вырезать, потому что кому-то это может быть полезно. Если хотите просто «поиграть» — ссылки выше.

Если хотите разобраться, как это устроено изнутри, — добро пожаловать под кат. Листайте диагонально, выхватывайте интересные куски, я постарался разбить на смысловые блоки.

Читать далее

Монорепозиторий с поддержкой Vite, TS, ESM и абсолютных импортов без расширений с использованием «subpath imports»

Уровень сложностиСредний
Время на прочтение12 мин
Охват и читатели4.8K

Абсолютные импорты без расширений в ESM-монорепозитории.

Настраиваем Vite, TypeScript и автоимпорты в IDE (VSCode) с помощью “subpath imports”.

Разрешаем конфликты настроек без костылей.

Добавляем приоритет автоимпорта папок в качестве модулей, при наличии “index.ts”.

Настраиваем Vite и TypeScript на работу с исходниками компилируемой библиотеки в dev-режиме.

Читать далее

Сторож бюджета сработал ровно так, как я его написал. Поэтому за сутки ушло 225 евро при жёстком пороге 150

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели4.8K

Я сам написал скрипт, который следит за расходом Telegram Ads и глушит кампании при превышении дневного лимита. Двадцать пятого июня он отработал ровно так, как был написан, — и именно поэтому за сутки открутилось 224,98 € при пороге 150. Разбираю по шагам, где именно я ошибся: почему проверка «раз в час» на самом деле проверяла не то, почему остановка кампании не остановила расход, и как алерт о проблеме ушёл туда, где его никто не читал. С кодом до и после.

Читать далее

Я отдал языковой модели доступ к продовой панели администрирования. Вот что пришлось построить, чтобы она её не сожгла

Уровень сложностиСложный
Время на прочтение18 мин
Охват и читатели7.8K

Полгода назад я поддерживал TypeScript SDK для одной панели администрирования. Обычная библиотека: сгенерированный из OpenAPI клиент, авторизация, ретраи, вебхуки. И в какой‑то момент я поймал себя на том, что рутинные вопросы к панели — «у кого истекает доступ на этой неделе», «почему нода отвалилась», «сколько трафика съел вот этот аккаунт» — я решаю одинаково: открываю редактор, пишу пятнадцать строк скрипта на своём же SDK, запускаю, читаю, удаляю.

Мысль напрашивалась: SDK уже типизирован, схемы уже есть, значит модель может вызывать его сама. Так появился marzban-mcp.

Дальше выяснилось, что «обернуть SDK в MCP» — это примерно 10% работы. Остальные 90% — ответ на вопрос, который в обычной библиотеке вообще не стоит: что можно доверить модели делать с боевой инфраструктурой, а что нельзя, и как эту границу выразить в коде.

Читать далее

Аналитика без cookie: дневной HMAC вместо идентификатора посетителя

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели7.6K

Внешний счётчик ставится за пять минут, и обычно этого достаточно. Но у модели «сторонний скрипт с чужого домена» есть технический потолок, и на магазине я в него упёрся: запрос к третьему домену режут блокировщики и антитрекинг браузеров, на объёме включается сэмплирование, cookie тянет за собой баннер согласия (а все, кто его отклонил, выпадают из статистики целиком), и главное — поведение ваших покупателей лежит в чужой системе, рядом с которой нет ваших заказов.

Ниже — как устроен свой cookieless‑трекинг в двух проектах на Next.js: интернет‑магазин (Next.js 15.5, TypeScript, Prisma 6, PostgreSQL) и маркетплейс услуг (тот же Next.js, но pg без ORM). Код в статье — из работающих проектов, с теми решениями, которые оказались неочевидными, и с теми, которые пришлось переделать.

Сразу оговорка: это не «Метрика — зло». Для контентного сайта внешний счётчик закрывает вопрос целиком. Разговор начинается там, где аналитика — часть продукта.

Читать далее
1
23 ...