Przejdź do głównej zawartości

Przepisy Node.js dla agentów AI to prompty i bramki weryfikacyjne, dzięki którym Claude Code, Codex i Cursor tworzą produkcyjne usługi Express 5 w TypeScripcie: czysty shutdown, walidację wejścia, rotację refresh tokenów, limity żądań, transakcje Prisma odporne na współbieżność, zadania BullMQ i logi z redakcją sekretów. Kod akceptujesz na podstawie wyników bramek, a nie lektury linijka po linijce.

Twoje API w Expressie przechodzi wszystkie testy napisane przez agenta, a potem pierwszy deploy zrywa trwające żądania, dwóch klientów kupuje ostatnią sztukę towaru w tej samej chwili, a refresh token pojawia się jawnym tekstem w wyszukiwarce logów. Kod wyglądał idiomatycznie. Każdy z tych błędów to produkcyjny szczegół, którego testy happy path nigdy nie dotknęły.

Ta strona jest dla programistów, którzy budują backendy Node.js z agentem i chcą przestać przeglądać każdy middleware wzrokiem. Produkcyjne szczegóły trafiają do promptów, a dowód dostarcza maszyna.

  • Blok reguł AGENTS.md dla TypeScriptu na Node.js, którego przestrzegają wszystkie trzy narzędzia, oraz bramkę npm run check, którą agent uruchamia, zanim powie „gotowe”
  • Siedem promptów do skopiowania: szkielet Express 5 z czystym shutdownem, walidacja i mapowanie błędów, rotacja refresh tokenów, rate limiting, transakcja zamówienia w Prisma, worker BullMQ oraz ustrukturyzowane logi z redakcją
  • Tabelę weryfikacji, która mówi, która bramka łapie który błąd, więc czytasz wynik bramek zamiast diffa
  • Kroki naprawcze dla sześciu najczęstszych awarii Node.js napisanego przez agenta

Przygotuj konwencje Node.js i bramkę, którą agent musi przejść

Dział zatytułowany „Przygotuj konwencje Node.js i bramkę, którą agent musi przejść”

Większość pracy wykonują dwa artefakty: plik reguł, który agent czyta przy każdym zadaniu, i jedno polecenie, które kończy się błędem, gdy kod nie jest gotowy. Przygotuj oba, zanim poprosisz o jakikolwiek kod.

  1. Przypnij wspieraną wersję środowiska. Według harmonogramu wydań Node.js Node.js 24 jest w fazie Active LTS do 2026-10-20, kiedy przechodzi w Maintenance LTS, Node.js 22 w fazie Maintenance LTS, a Node.js 20 osiągnął koniec wsparcia 2026-04-30. Node.js 26 ma zostać wersją LTS 2026-10-28. Przypnij 24 w .nvmrc i w package.json:

    {
    "type": "module",
    "engines": { "node": ">=24" }
    }

    Jawna wersja powstrzymuje agenta przed obejściami, których aktualny Node.js już nie potrzebuje, na przykład dotenv tam, gdzie działa node --env-file=.env.

  2. Dodaj bramkę do package.json. To definicja „gotowe” dla każdego promptu na tej stronie.

    {
    "scripts": {
    "typecheck": "tsc --noEmit",
    "lint": "eslint .",
    "test": "vitest run",
    "check": "npm run typecheck && npm run lint && npm run test && npm audit --omit=dev --audit-level=high"
    }
    }

    Aktualne wersje w npm na 2026-09-26: express 5.2.1, zod 4.6.5, vitest 5.0.2, supertest 7.3.0, pino 10.3.1, bullmq 6.3.9, @prisma/client 7.10.0, testcontainers 12.1.0. Dwa pakiety wymagają uwagi, a sekcja o awariach wyjaśnia dlaczego: instaluj typescript@~6.0.3 zamiast latest, jeśli używasz reguł typescript-eslint opartych na typach, oraz instaluj prisma i @prisma/client w tej samej wersji.

  3. Zapisz reguły Node.js w AGENTS.md w katalogu głównym repozytorium. Codex czyta AGENTS.md natywnie; zakładki poniżej pokazują, jak Claude Code go wczytuje i jak Cursor dostaje jego kopię.

    ## Node.js conventions
    - Node.js 24, ESM, TypeScript strict. Express 5, never Express 4 idioms.
    - Express 5 forwards rejected promises from handlers to the error middleware.
    Do not add express-async-errors or a catchAsync wrapper.
    - Named wildcards only: app.all('/*splat', ...), never app.get('*', ...).
    - Config comes from one Zod-validated module, src/config.ts. No process.env
    reads anywhere else.
    - One PrismaClient for the process, created in src/db.ts. Never per request.
    - Every error response uses { error: { code, message } }; no stack traces
    outside development.
    - Tests: Vitest and supertest. Database tests use Testcontainers, not mocks.
    - Never edit an existing test assertion, add .skip, or add .only to make a
    test pass. If a test looks wrong, stop and say why.
    - Done means `npm run check` passes. Paste its last 20 lines in your final message.

Najważniejsze są dwie ostatnie reguły. Pierwsza nie pozwala agentowi osłabiać testów, żeby dojść do zielonego wyniku; w artykule chroń wyrocznię znajdziesz wyjaśnienie, dlaczego to najczęstszy sposób, w jaki praca agenta udaje sukces. Druga zamienia „chyba działa” w dowód, który przeczytasz w dziesięć sekund.

Reguły i prompty są identyczne we wszystkich narzędziach. Różni się to, jak każde narzędzie wczytuje reguły, formatuje zmiany i recenzuje wynik.

Claude Code w pierwszej kolejności czyta CLAUDE.md, więc utwórz plik, który importuje wspólne reguły. Składnia @path wstawia plik do kontekstu przy starcie:

@AGENTS.md

Bez pliku CLAUDE.md Claude Code w wersji v2.1.277 i nowszej (oba kanały wydań, stan na 2026-10-12) czyta AGENTS.md bezpośrednio (v2.1.281 na Bedrocku, Google Cloud, Foundry i bramkach LLM; przełącznik w /config → Project instructions); import ma znaczenie, gdy trzymasz też reguły specyficzne dla Claude.

Formatuj każdy plik TypeScript edytowany przez agenta hookiem PostToolUse w .claude/settings.json (wymaga Prettiera w devDependencies: npm install -D prettier):

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | grep -E '\\.(ts|js)$' | xargs -r npx --no-install prettier --write"
}
]
}
]
}
}

Daj agentowi wyszukiwanie referencji i diagnostykę przez plugin typescript-lsp z oficjalnego marketplace’u Anthropic. Plugin tylko rejestruje serwer, więc najpierw zainstaluj serwer języka. Przypnij typescript@6: TypeScript 7.0.2 zawiera tylko tsc, bez tsserver, którego serwer języka potrzebuje (sprawdzono 2026-09-26). W terminalu:

Okno terminala
npm install -g typescript-language-server typescript@6
claude plugin install typescript-lsp@claude-plugins-official

Zanim otworzysz pull request, uruchom w sesji /code-review, żeby dostać drugą opinię o diffie.

Zacznij od domyślnego modelu narzędzia i zwiększ poziom effort, zanim zmienisz model; aktualne domyślne modele znajdziesz w przeglądzie modeli.

Zbuduj produkcyjne API na Express 5 z agentem krok po kroku

Dział zatytułowany „Zbuduj produkcyjne API na Express 5 z agentem krok po kroku”

Każdy krok to jeden prompt i sprawdzenie, które go dowodzi. Wykonuj je po kolei: późniejsze prompty zakładają, że szkielet i moduł bazy danych już istnieją.

Jak wygenerować usługę Express 5, która czysto się zamyka?

Dział zatytułowany „Jak wygenerować usługę Express 5, która czysto się zamyka?”

Najczęstsze pominięcie w pierwszym podejściu to shutdown. Agent wywołuje app.listen() i nic więcej, więc każdy deploy przerywa trwające żądania i zostawia otwarte połączenia z bazą.

Dobra odpowiedź ma taki rdzeń:

const server = app.listen(config.PORT);
function shutdown(signal: NodeJS.Signals) {
logger.info({ signal }, 'shutting down');
setTimeout(() => process.exit(1), 10_000).unref();
server.close(async (err) => {
await prisma.$disconnect();
await redis.quit();
process.exit(err ? 1 : 0);
});
}
process.once('SIGTERM', shutdown);
process.once('SIGINT', shutdown);

Nie musisz tego sprawdzać wzrokiem: test nie przejdzie, jeśli żądanie zostanie zerwane albo proces zawiśnie. Rozdzielenie app.ts i server.ts pozwala też supertestowi sterować aplikacją bez otwierania portu.

Jak uzyskać walidację i odpowiedzi błędów, na których klient może polegać?

Dział zatytułowany „Jak uzyskać walidację i odpowiedzi błędów, na których klient może polegać?”

Agenci wytrenowani na Expressie 4 owijają każdy handler w catchAsync albo instalują express-async-errors. Express 5 sam przekazuje odrzucone obietnice z handlerów do middleware’u błędów, więc te wrappery to martwy kod, a reguła w AGENTS.md trzyma je z dala od repozytorium.

Agenci zwykle pomijają właśnie mapowanie błędów Prismy. Bez niego zduplikowany e-mail kończy się kodem 500, a klient ponawia żądanie, które nigdy się nie powiedzie. Test błędu 500 w trybie produkcyjnym dowodzi, że żaden wewnętrzny szczegół nie trafia do klienta.

Jak skłonić agenta do napisania rotacji refresh tokenów, której można ufać?

Dział zatytułowany „Jak skłonić agenta do napisania rotacji refresh tokenów, której można ufać?”

Kod uwierzytelniania to miejsce, w którym czytanie diffa daje największe poczucie bezpieczeństwa i najmniej realnej pewności. Opisz scenariusze ataku jako testy i to one niech niosą dowód.

Kluczowy jest test ponownego użycia tokenu. Bez niego implementacja, która nigdy nie unieważnia starego tokenu, przechodzi wszystkie pozostałe przypadki. Jako drugie, niezależne sprawdzenie tego kodu dodaj bramkę bezpieczeństwa, która uruchamia agenta recenzującego przy każdym pull requeście; opcje dla każdego narzędzia opisuje strona o bramkach bezpieczeństwa dla agentów.

Jak ograniczyć liczbę żądań do API w Expressie za load balancerem?

Dział zatytułowany „Jak ograniczyć liczbę żądań do API w Expressie za load balancerem?”

Wygenerowany limiter zwykle działa lokalnie i zawodzi na produkcji na jeden z dwóch sposobów: liczniki żyją w pamięci procesu, więc każda replika przepuszcza pełny limit, albo każde żądanie wygląda, jakby przyszło z adresu IP load balancera.

Test z dwiema instancjami dowodzi, że magazyn jest wspólny; test w jednym procesie przechodzi z domyślnym magazynem w pamięci i nie mówi nic o produkcji.

Jak uzyskać transakcje Prisma, które wytrzymają równoległe zamówienia?

Dział zatytułowany „Jak uzyskać transakcje Prisma, które wytrzymają równoległe zamówienia?”

Pierwsza próba agenta przy „sprawdź stan, potem zmniejsz” odczytuje stan magazynu, porównuje go w JavaScripcie i zapisuje z powrotem. Dwa równoległe zamówienia odczytują stock = 1 i oba kończą się sukcesem. Zamockowane repozytorium nie pokaże tego błędu; pokaże go tylko prawdziwa baza pod równoległymi żądaniami.

Dwa szczegóły Prisma, których agent może nie znać. Prisma 7 wymaga driver adaptera: klienta tworzy się jako new PrismaClient({ adapter: new PrismaPg({ connectionString }) }) z generatorem prisma-client i plikiem prisma.config.ts, więc ustawienia puli należą do adaptera, a nie do connection stringa. Poza tym 2026-09-26 tag latest w npm dla CLI prisma wskazuje 8.0.0-rc.17, czyli release candidate nowego CLI Prisma dla Prisma Developer Platform, podczas gdy latest dla @prisma/client to 7.10.0. Prisma 8 dostarcza własne skille dla agentów (npx prisma skills sync instaluje je w .claude/skills/, .cursor/skills/ i .agents/skills/), co czyni ją atrakcyjną dla nowych projektów. Wybierz ją świadomie, a nie dlatego, że tak zdecydowało npm install prisma.

Żeby agent czytał prawdziwy schemat zamiast zgadywać nazwy kolumn, podłącz serwer MCP bazy danych do bazy deweloperskiej przez rolę tylko do odczytu. Przewodnik po MCP dla baz danych porównuje serwery i ich przełączniki trybu tylko do odczytu. Nie używaj @modelcontextprotocol/server-postgres: npm oznacza go jako przestarzały.

Jak przenieść wolną pracę do kolejki BullMQ, nie gubiąc zadań?

Dział zatytułowany „Jak przenieść wolną pracę do kolejki BullMQ, nie gubiąc zadań?”

Pierwsza wersja agenta wykonuje pracę wewnątrz żądania albo ponawia nieidempotentne zadanie i wysyła e-mail dwa razy.

Test idempotencji sprawia, że ponowienia są bezpieczne. Bez niego ponowienie po timeoucie, który nastąpił już po udanym zapisie, tworzy zduplikowane pliki, e-maile lub obciążenia karty.

Jak uzyskać ustrukturyzowane logi, które nigdy nie ujawniają sekretów?

Dział zatytułowany „Jak uzyskać ustrukturyzowane logi, które nigdy nie ujawniają sekretów?”

Pierwsza wersja agenta loguje req.body, więc hasła i tokeny trafiają do wyszukiwarki logów.

Test redakcji to jedyny sposób, żeby wiedzieć, że redakcja działa; ścieżka, która nie pasuje do rzeczywistego kształtu obiektu, zawodzi po cichu. Dashboardy, alerty i tracing na bazie tych logów opisują wzorce monitoringu i logowania.

Jak zweryfikować Node.js napisany przez agenta bez czytania każdej linijki?

Dział zatytułowany „Jak zweryfikować Node.js napisany przez agenta bez czytania każdej linijki?”

Czytaj wynik bramek i listy przypadków testowych, a nie diff. Każda bramka poniżej łapie klasę błędów, która w code review wygląda poprawnie.

BramkaPolecenieCo łapie
Typytsc --noEmitNiezgodne kształty danych między warstwami, nieobsłużone undefined, literówki w polach
Lintereslint . z regułami typescript-eslint opartymi na typachPorzucone obietnice (no-floating-promises), niewłaściwie użyte obietnice w callbackach (no-misused-promises), niebezpieczne any
Testy jednostkowe i HTTPvitest run z supertestemKody statusu, treść błędów, walidacja, redakcja, shutdown
Testy integracyjneTestcontainers z Postgresem i RedisemBłędny SQL, brakujące ograniczenia unikalności, wyścigi takie jak nadsprzedaż, wspólne liczniki rate limitu
Zależnościnpm audit --omit=dev --audit-level=highZnane podatności w zależnościach produkcyjnych
Obciążenienpx autocannon -c 100 -d 30 https://staging.example.com/api/v1/orders na staginguWyczerpanie puli, blokowanie pętli zdarzeń, rosnące zużycie pamięci
Agent recenzujący/code-review (Claude Code), codex review --base main (Codex), Bugbot (Cursor)Błędy logiczne i brakujące przypadki, których bramki nie wyrażą

Na szczególną uwagę zasługuje no-floating-promises: obietnica, na którą agent zapomniał dać await, staje się nieobsłużonym odrzuceniem, a Node.js domyślnie kończy proces przy nieobsłużonych odrzuceniach od wersji 15. Mocniejszy dowód, że same testy są dobre, opisuje strona o testach mutacyjnych i sile wyroczni.

Pięć pierwszych bramek uruchamiaj w CI przy każdym pull requeście; plik workflow znajdziesz we wzorcach pipeline’ów CI/CD. Inżynier odpowiedzialny za usługę zatwierdza trzy rzeczy: listy przypadków testowych, zieloną bramkę i wynik testu obciążeniowego. Ludzka lektura trafia do fragmentów oznaczonych przez agenta recenzującego oraz do kodu, który dotyka uwierzytelniania, pieniędzy lub transakcji. Podział tej pracy w zespole opisuje recenzja PR z agentem.

Gdy Node.js napisany przez agenta psuje się na produkcji

Dział zatytułowany „Gdy Node.js napisany przez agenta psuje się na produkcji”

Każda z poniższych awarii przechodzi zestaw testów happy path. Każda ma objaw, który wykryjesz, i sposób naprawy, który zastosujesz.

  • Nadsprzedaż albo podwójne przetwarzanie pod obciążeniem. Objaw: ujemny stan magazynu, zduplikowane zamówienia lub e-maile po skoku ruchu. Przyczyna: logika „odczytaj, a potem zapisz” poza jedną atomową instrukcją albo nieidempotentne zadanie, które zostało ponowione. Naprawa: dodaj współbieżny test Testcontainers z przepisu o Prisma, a potem użyj promptu: „Find every place that reads a value, decides in JavaScript, and writes it back. Replace each with a conditional update or a row lock, and add a concurrent test for each.”
  • Wyczerpanie połączeń. Objaw: żądania wiszą, a potem kończą się timeoutem, choć CPU bazy jest niskie. Przyczyna: new PrismaClient() na żądanie albo na moduł, często dodane, gdy agent tworzy nowy plik. Naprawa: grep -rn "new PrismaClient" src/ musi zwracać jedną linię. Sam grep kończy się kodem 0 w obu przypadkach, więc testem musi być liczba linii: dodaj do scripts wpis "check:prisma": "test $(grep -rn 'new PrismaClient' src/ | wc -l) -eq 1" i dopisz && npm run check:prisma do check, żeby bramka odrzucała drugiego klienta.
  • Idiomy Expressa 4 w aplikacji na Expressie 5. Objaw: serwer nie startuje z błędem path-to-regexp „Missing parameter name” albo wrapper catchAsync ukrywa błąd. Przyczyna: dane treningowe zdominowane przez Express 4. Naprawa: użyj promptu: „Migrate this codebase to Express 5 idioms: name every wildcard route (/*splat), delete catchAsync and express-async-errors, and change no behaviour. Done means npm run check passes.”
  • Wszyscy naraz dostają limit. Objaw: skok odpowiedzi 429 u wszystkich użytkowników albo błąd walidacji express-rate-limit dotyczący X-Forwarded-For. Przyczyna: brak trust proxy lub wartość niezgodna z liczbą proxy, więc wszyscy klienci dzielą adres IP load balancera. Naprawa: ustaw trust proxy na rzeczywistą liczbę przeskoków i sprawdź w teście, że req.ip to adres klienta, gdy ustawiony jest X-Forwarded-For.
  • Instalacja psuje się na tagach wersji. Objaw: npm install kończy się błędem ERESOLVE, bo typescript-eslint 8.70.1 deklaruje typescript <6.1.0, a typescript@latest to 7.0.2, albo wynik prisma generate przestaje pasować do klienta, bo CLI pochodzi z release candidate Prisma 8. Naprawa: przypnij oba pakiety do dokładnych wersji w package.json, zacommituj lockfile i zapisz w AGENTS.md, że agent nie zmienia przypiętych wersji bez pytania.
  • Agent osłabia test, żeby dojść do zielonego wyniku. Objaw: poluzowana asercja, usunięty przypadek albo dodane .skip w tym samym diffie co poprawka. Naprawa: przywróć plik testu, powtórz regułę z AGENTS.md i skonfiguruj CI tak, żeby odrzucał pull request zmieniający istniejący *.test.ts bez etykiety test-change.

Czy ten artykuł Ci pomógł?

Jedno kliknięcie, bez logowania.

wcale bardzo