stack i tech
JavaScript i TypeScript w warstwie workflow.
n8n jest napisany w TypeScripcie, więc kiedy trzeba rozszerzyć go o coś, czego out-of-the-box nie robi, najczystszą drogą jest napisanie custom node'a w TS. Plus Playwright dla legalnego scrapingu i Node.js mikroserwis, gdy Python byłby cięższy niż zysk.
Kiedy TypeScript wchodzi do automatyzacji
Cztery miejsca, gdzie sięgam po TypeScript, zamiast zostać w Pythonie albo czystym n8n:
- Custom node'y do n8n: n8n API dla custom nodes jest w TypeScripcie. Pisanie własnego node'a w TS daje autocomplete, type-safe dostęp do
INodeType, naturalne wsparcie dla asynchroniczności i spójność z ekosystemem n8n. - Playwright dla legalnego scrapingu: biblioteki Playwright są najdojrzalsze w TypeScripcie, asynchroniczne callbacki prostsze w pisaniu z async/await, debugowanie przez
--debugi selectory wspierane bezpośrednio w API. - Microservices, które integrują się blisko z frontend: jeśli klient ma Next.js albo SvelteKit, a automatyzacja zwraca wyniki do UI, TypeScript po obu stronach dzieli typy przez wspólne pakiety (monorepo z Turborepo albo pnpm workspaces).
- Workflow'y z mocno asynchronicznym IO: pobieranie z wielu API równolegle, agregacja, streaming plików. Node.js event loop plus
Promise.all()daje wyraźnie większy throughput niż sync Python przy takich scenariuszach.
Kiedy odpuszczam TS: proste transformacje danych (Python pandas wygrywa), ETL do data warehouse (Airflow lepiej pasuje), klasyczne skrypty cronowe (bash albo Python oszczędza linii kodu).
Custom node'y n8n w TypeScripcie
Struktura projektu custom node'a, który faktycznie trafia do produkcji:
- Scaffold przez
n8n-nodes-starter: oficjalny template n8n.io. Dajepackage.json,tsconfig.json,gulpfile.jsdla buildu ikon, gotowy eslint. - Struktura kodu: klasa implementująca
INodeType, metodaexecute()dla logiki,descriptiondla UI. Parametry deklarowane wproperties[]automatycznie generują formularz w n8n. - Publikacja: npm publish pod własną scope'ą (na przykład
@workinflows/n8n-nodes-polish-erp), instalacja w n8n przezN8N_COMMUNITY_PACKAGES_ENABLED=truei panel Community Nodes. - Testy: integracyjne z mockiem
IExecuteFunctions, unit testy dla helperów. Jest, aby CI/CD nie wypuszczał buggy wersji.
Kiedy custom node, a kiedy HTTP Request Node
Custom node ma sens, gdy integracja wraca w wielu workflow (np. polski ERP używany w 5 klientach) albo wymaga złożonej logiki (OAuth refresh tokens, pagination, rate limiting). Dla prostej integracji z nowym REST API wystarcza HTTP Request Node plus Function Node na obróbkę. Czas build'u custom node'a (włącznie z testami) to 8-20 godzin, opłaca się tylko przy wielokrotnym użyciu.
Playwright jako legalny scraper
Playwright używam do scenariuszy, w których API nie istnieje albo nie pokrywa tego, czego klient potrzebuje:
- LinkedIn Sales Navigator scraping (legalny z sesji klienta): klient ma konto, skrypt uruchamia przeglądarkę w profilu użytkownika, scrolluje listę leadów, zapisuje do bazy. Respektuje rate limity LinkedIn (pauza 2-5 sek między akcjami).
- Pobieranie faktur z portali dostawców bez API: operatorzy telekomunikacyjni, dostawcy energii, portale B2B. Playwright loguje się przez SSO albo user/pass, nawiguje do archiwum, pobiera PDF. Z cron job raz dziennie.
- Monitoring dostępności usługi konkurenta: jeśli konkurent zmieni cennik na stronie, Playwright to zauważy i wyśle alert. Etyczne ograniczenia: tylko publiczne strony, respect robots.txt, nie obciążamy serwera.
Ważne: scraping musi mieścić się w ramach prawa (RODO, prawa autorskie, warunki korzystania z serwisów). Przed wdrożeniem sprawdzam Terms of Service i konsultuję z działem prawnym klienta, gdy jest wątpliwość. Wbrew pozorom wiele scenariuszy jest legalnie możliwych, jeśli jest się osobą zalogowaną z uprawnieniami do tych danych.
Node.js microservices obok n8n
Express albo Fastify jako warstwa między n8n a zewnętrznym światem. Typowe use case'y:
- Webhook receiver dla third-party callbacks: Stripe, HubSpot, Meta Ads. Microservice waliduje podpis, normalizuje payload, wypycha do n8n przez HTTP albo message queue. n8n dostaje ustandaryzowany format.
- Proxy dla API, które wymaga pre-processingu: integracja, gdzie musisz podpisać request JWT, odszyfrować response, dodać metadane. TypeScript microservice robi to cleanly, n8n woła go jak zwykły endpoint.
- Rate limiter i cache warstwa: jeśli wiele workflow odpytuje to samo zewnętrzne API (np. kurs walut NBP), microservice trzyma cache w Redisie i rate limiter globalnie dla wszystkich workflow.
Stack, którego używam: Node.js 22 LTS, TypeScript 5.7, Fastify (szybszy od Express przy porównywalnym DX), Zod do walidacji, Pino dla structured logging. Deployment: Docker, alpine image z multi-stage build.
Pułapki, w które wpadają zespoły
Problemy, które regularnie widzę przy projektach TS w automatyzacji:
- Brak strict mode w tsconfig:
strict: falsedaje typy any w większości miejsc, kompiluje ale łapie błędy dopiero w runtime. Zawszestrict: trueplusnoUncheckedIndexedAccess. - Blocking operacje w event loopie: CPU-intensive task (parsowanie dużego XML, obróbka obrazu) w głównym wątku zawiesza całość. Użyj
worker_threadsalbo wydzieli do osobnego microservice. - Nieobsłużone promise rejections:
process.on('unhandledRejection', ...)jako safety net. Każdy awaited call ma try/catch albo.catch(). - Brak graceful shutdown: Docker wysyła SIGTERM przy stop, Node.js domyślnie nie zamyka połączeń bazy ani nie czeka na in-flight requests. Dodaj
process.on('SIGTERM', async () => ...)z cleanup. - Over-abstrahowanie custom nodes: pisanie custom node'a pod każdą integrację, nawet jednorazową. Jeśli integracja użyta tylko raz, HTTP Request Node plus Code Node wystarczy.
Najczęstsze pytania
Czy potrzebujemy frontend developera, żeby wdrożyć TS microservice?
Nie. TypeScript w automatyzacji to backend-focused Node.js, nie frontend. Wymaga podstawowej znajomości Node.js i npm, co w zespołach IT jest zwykle już obecne. Frontend dev (React, Vue) to osobna specjalizacja.
Dlaczego wybierasz TS zamiast JavaScript bez typów?
TypeScript łapie w kompilacji 70 procent bugów, które JS zobaczyłby dopiero w runtime. Dla custom nodes n8n TS jest wymagany przez oficjalny template. Dla mikroserwisów: koszt setup jest minimalny, a benefit w długoterminowym utrzymaniu wyraźny (refactor, autocomplete, dokumentacja typów).
Czy możemy publikować custom node n8n jako open-source?
Tak i zachęcam, gdy integracja dotyczy generycznego narzędzia (polski ERP, nisza lokalna). Publikacja na npm daje widoczność i buduje reputację. Dla integracji specyficznych dla klienta (np. custom wewnętrzny system) trzymamy node prywatnie, jako scoped package na rejestracji firmowej.
Node.js 22 czy starsze wersje?
Node.js 22 LTS dla nowych projektów (od października 2024 LTS). Dla istniejącego stack'u klienta trzymam się jego wersji, minimum Node.js 20. Starsze niż 20 wymagają rozmowy, bo część bibliotek (Fastify 5+, Vitest 3+) wymaga nowoczesnego Node.
Czy TypeScript zastępuje testy?
Nie. Typy ochrany przed strukturalnymi błędami (zła nazwa pola, zła arność funkcji), ale nie przed logicznymi (złe obliczenie VAT, zły warunek if). Testy jednostkowe i integracyjne dalej są konieczne. Dla n8n custom nodes minimum: test execute() z różnymi inputami i mock IExecuteFunctions.
Chcesz pogadać o konkretnym projekcie?
Warsztat otwierający to 90 minut, zdalnie albo w Poznaniu, bez zobowiązań. Mówimy, czy Twój proces nadaje się do automatyzacji i w jakiej skali.
napisz do mnie → adi@workinflows.pl · LinkedIn