npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nuxt-error-tracker

v0.1.19

Published

[English](./README.md) · **Українська**

Readme

nuxt-error-tracker

English · Українська

Легкий трекер frontend-помилок для Nuxt 3 / 4. Перехоплює неопрацьовані помилки, невдалі запити та ланцюжок дій користувача (breadcrumbs), після чого відправляє їх на ваш власний Observer ingest-endpoint. Працює лише на клієнті, батчами, і збудований так, щоб ніколи не ламати застосунок-хост — якщо його не налаштовано, він не робить нічого.

Ви даєте URL і публічний ключ; пакет робить перехоплення. Усе відправлене потрапляє під ваш проєкт у вашому Observer-дашборді, де ви самі переглядаєте, шукаєте та керуєте логами.


Зміст


Як це працює (складові)

Складових три. Цей пакет — лише перша.

| Складова | Що це | За що відповідає | | --- | --- | --- | | Цей пакет (nuxt-error-tracker) | Nuxt-модуль, який ви ставите у застосунок | Підключається до браузера, перехоплює помилки + breadcrumbs, батчить їх і POSTить на ваш endpoint. Працює лише на клієнті. | | Ваш ingest-endpoint (.../v1/ingest) | Observer API, який ви хостите (або маєте доступ) | Автентифікує запит за публічним ключем + origin, валідує та rate-лімітує, дедуплікує помилки за fingerprint і зберігає. | | Ваш дашборд | Консоль Observer | Де ви переглядаєте, шукаєте та керуєте логами — стек-трейси, occurrences, breadcrumb-ланцюжки, retention. |

Пакет ніколи не вирішує, куди йдуть дані — вирішуєте ви, вказавши endpoint на свій хост. Дефолтного URL немає. Змініть хост — логи підуть за ним. Це і є «bring your own backend»: той самий пакет працює проти localhost під час розробки та проти вашого прод-Observer у релізі, лише зміною endpoint.

Усередині самого пакета:

  • module.ts — Nuxt-модуль. Читає ваші опції та реєструє плагін перехоплення лише коли enabled + endpoint + publicKey присутні всі. Немає будь-чого → плагін не додається, застосунок працює недоторканим. Також нормалізує опції (обрізає maxBatch ≤ 20, maxBreadcrumbs ≤ 50 під серверні ліміти) і додає TypeScript-типи для хелперів.
  • plugin.client.ts — власне рушій перехоплення (лише браузер). Слухає помилки, обгортає fetch, патчить console.error, пише breadcrumbs і керує чергою відправки.
  • plugin.server.ts — маленька SSR-заглушка. Дає no-op $trackError / $addBreadcrumb, щоб виклик під час серверного рендеру ніколи не кидав помилку.
  • ingest.codec.ts — саморобний protobuf-енкодер (без залежностей), що перетворює батч на бінарний формат, який очікує API.

Встановлення

npm i nuxt-error-tracker
# або: bun add nuxt-error-tracker

Отримати endpoint і ключ

Модулю потрібні рівно дві речі, щоб почати звітувати: ingest-endpoint (ваш URL) і публічний ключ (якому проєкту належать помилки). Обидва беруться з вашого Observer-дашборда.

  1. Відкрийте дашборд за адресою https://<ваш-observer-хост>/dashboard.
  2. Створіть акаунт — введіть email і пароль (мін. 8 символів), надішліть. Ви лишаєтесь залогіненим через захищений httpOnly-cookie.
  3. Натисніть New project, дайте назву (напр. my-app) і за бажанням перелічіть origins, на яких працює ваш сайт (через кому, напр. https://my-app.com, http://localhost:3000). Порожньо = приймати будь-який origin. Це серверний allowlist — запити з інших origins відхиляються.
  4. Проєкт тепер показує публічний ключ (pk_…) і готовий сніпет nuxt.config. Використайте Copy key / Copy config.
  5. Endpoint — це ваш хост + /v1/ingest, тобто https://<ваш-observer-хост>/v1/ingest.

Що насправді роблять ці два значення

  • endpointкуди відправляти. Це ваш URL. Вказуйте на будь-який хост, де крутиться Observer API. Хостованого дефолту немає; ви завжди шлете на свій бекенд.
  • publicKeyчий проєкт помилки. На кожному запиті API шукає проєкт за цим ключем (заголовок X-Public-Key або query ?key= для beacon-шляху), потім застосовує allowlist origins і rate-ліміт цього проєкту. Це публічне значення — безпечно класти у клієнтські бандли. Воно дає лише запис (ingest) в один проєкт; воно не дає нікому читати ваші логи. Читання вимагає логіну в дашборд.

Origins важливі. Якщо ви задали allowlist, він мусить містити кожен origin, з якого віддається застосунок — прод-домени та http://localhost:3000 для локальної розробки — інакше запити браузера отримають 401. Лишіть порожнім під час експериментів, звузьте для продакшену.

Після налаштування (нижче) і деплою перехоплені помилки з'являються під цим проєктом у дашборді. Відкрийте Logs на проєкті, щоб їх переглянути.


Налаштування

Додайте модуль і вкажіть йому ingest-endpoint з публічним ключем вашого проєкту:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-error-tracker'],
  errorTracker: {
    endpoint: 'https://<ваш-observer-хост>/v1/ingest',
    publicKey: 'pk_xxxxxxxxxxxxxxxxxxxxxxxx',
  },
})

Це мінімум. Усе решта має розумні дефолти.

Немає ключів? Не проблема

Якщо endpoint чи publicKey порожні (або enabled: false), плагін не реєструється, і застосунок працює недоторканим. Тому модуль можна лишати встановленим, підключаючи ключі по-середовищах — dev-збірки без ключа просто не трекають. Ні падіння, ні шуму в консолі, ні мережевого виклику.


Конфігурація через змінні середовища

Кожну опцію можна задати зі змінних середовища замість хардкоду, за конвенцією публічних env у Nuxt runtimeConfig:

NUXT_PUBLIC_ERROR_TRACKER_ENDPOINT=https://<ваш-observer-хост>/v1/ingest
NUXT_PUBLIC_ERROR_TRACKER_PUBLIC_KEY=pk_xxxxxxxxxxxxxxxxxxxxxxxx
NUXT_PUBLIC_ERROR_TRACKER_APP_VERSION=1.4.2

Підключіть їх у nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['nuxt-error-tracker'],
  runtimeConfig: {
    public: {
      errorTracker: {
        endpoint: process.env.NUXT_PUBLIC_ERROR_TRACKER_ENDPOINT,
        publicKey: process.env.NUXT_PUBLIC_ERROR_TRACKER_PUBLIC_KEY,
        appVersion: process.env.NUXT_PUBLIC_ERROR_TRACKER_APP_VERSION,
      },
    },
  },
})

Це рекомендований спосіб націлити ту саму збірку на різний endpoint за середовищем (staging vs. production) без правки коду.


Опції

| Опція | Тип | Дефолт | Опис | | --------------------- | --------- | ----------- | ------------------------------------------------------------------ | | endpoint | string | '' | Ingest URL (.../v1/ingest). Обовʼязково — ваш хост. | | publicKey | string | '' | Публічний ключ вашого проєкту (pk_…). Обовʼязково. | | appVersion | string | 'unknown' | Тегує кожен батч релізом/версією для фільтрації. | | enabled | boolean | true | Головний вимикач. false = повністю вимкнено, плагін не реєструється. | | captureFetch | boolean | true | Обгортає fetch, щоб breadcrumbʼити запити і звітувати про збої / 5xx. | | captureFetchDetails | boolean | true | Додає повну деталь запиту/відповіді (метод, статус, тайминг, заголовки, тіло запиту, тіло відповіді) до кожного fetch-breadcrumb. Чутливі заголовки редагуються, тіла обрізаються до 2 КБ. false — лишити fetch-крихти лише-повідомленням (не захоплювати payload / PII). | | captureConsole | boolean | true | Патчить console.error, щоб ловити залоговані-але-не-кинуті помилки. | | captureInputs | boolean | false | Записує значення полів форм як breadcrumbs (на change/blur). Чутливі поля маскуються. Opt-in — захоплює введені користувачем дані. | | flushDelay | number | 2000 | Debounce (мс) перед відправкою черги-батча. | | minFlushInterval | number | 0 | Мін. пауза (мс) між флашами — throttle частоти запитів під час шторму помилок. 0 = вимкнено. | | sampleRate | number | 1 | Частка (0..1) захоплених помилок, що реально шлються; решта дропається при capture. 0.3 ≈ 30%. Ріже обʼєм до серверного rate limit. | | maxPerMinute | number | 0 | Клієнтський ліміт помилок у чергу за rolling-хвилину (fixed window); понад — дроп. Дзеркалить серверний per-project rate limit. 0 = без ліміту. | | maxPerSession | number | 5 | Макс. кількість occurrences тієї самої помилки за сесію. | | maxBatch | number | 20 | Макс. помилок на запит (обрізається серверним лімітом 20). | | maxBreadcrumbs | number | 30 | Breadcrumbs у ring buffer / на помилку (обрізається до 50). |


Runtime-хелпери

Плагін інʼєктить два хелпери для ручного використання:

const { $trackError, $addBreadcrumb } = useNuxtApp()

// Звітувати про опрацьовану помилку самому — опційний рівень серйозності
// ('fatal' | 'error' | 'warning' | 'info' | 'debug', дефолт 'error')
try {
  await mayFail()
} catch (e) {
  $trackError(e, 'warning')
}

// Додати власний breadcrumb у ланцюжок
$addBreadcrumb({
  type: 'custom',
  category: 'checkout',
  message: 'user clicked pay',
  level: 'info',
})

Обидва хелпери завжди викликаються. Реальне перехоплення — лише на клієнті; на сервері (SSR — напр. верхньорівневий <script setup>) це безпечні no-opʼи, тож виклик ніколи не кидає помилку.

$trackError і $addBreadcrumb повністю типізовані — модуль постачає augmentation для NuxtApp і Vue ComponentCustomProperties, тож і useNuxtApp(), і використання в шаблоні бачать їх як функції (без unknown / TS18046). Ручний .d.ts не потрібен.


Що відправляється на API

Нічого не відправляється, доки не станеться помилка. Пакет тримає в памʼяті ring buffer breadcrumbs, поки користувач взаємодіє; при перехопленні помилки він знімає снапшот цього ланцюжка, ставить помилку в чергу і (після debounce) POSTить батч.

Батч має дві частини: meta (раз на батч, застосовується до всіх помилок у ньому) і errors (масив перехоплених помилок).

meta (раз на батч)

| Поле | Тип | Джерело | Нотатки | | ------------ | -------- | ------- | ------- | | device | object | navigator / window | userAgent, language, platform, screen (ШxВ), viewport (ШxВ), online (bool), memory (deviceMemory, ГБ або null), connection (effectiveType або null). Сервер обрізає JSON до 2 КБ. | | userId | string | null | cookie user_id | Читається з cookie user_id, якщо є, інакше null. Пакет ніколи не вигадує id. Макс. 100 символів. | | appVersion | string | ваша опція appVersion | Дефолт 'unknown'. Макс. 50 символів. |

errors[] (на кожну перехоплену помилку)

| Поле | Тип | Опис | Ліміт | | ------------- | --------- | ---- | ----- | | message | string | Повідомлення помилки. | ≤ 1000 симв. | | stack | string | Стек-трейс. | ≤ 8000 симв. | | source | string | Звідки: vue, window, promise, fetch чи console. | ≤ 20 симв. | | level | string | Серйозність: fatal | error | warning | info | debug. | одне зі списку | | url | string | window.location.href на момент перехоплення. | ≤ 2000 симв. | | route | string | Nuxt-route fullPath. | ≤ 500 симв. | | occurredAt | string | ISO-8601 timestamp. | ISO-8601 | | breadcrumbs | Breadcrumb[] | Ланцюжок, що привів до помилки (нижче). | ≤ 50 елементів |

Кожен Breadcrumb:

| Поле | Тип | Опис | Ліміт | | ----------- | -------- | ---- | ----- | | type | string | click, input, navigation, fetch, console чи ваш кастомний тип. | ≤ 30 симв. | | category | string | напр. ui.click, ui.input, navigation, http, console. | ≤ 60 симв. | | message | string | Людиночитний рядок, напр. POST /api/pay → 500. | ≤ 500 симв. | | level | string | info | error | … | ≤ 20 симв. | | timestamp | string | ISO-8601. | ISO-8601 | | data | object | Опційний структурований payload (деталі fetch: метод, статус, тайминг, заголовки, тіла запиту/відповіді). | JSON |

Ліміти батча: щонайбільше 20 помилок на запит; клієнт також повертає в чергу невдалі батчі (обмежено 200 у памʼяті) і дедуплікує ту саму помилку до maxPerSession (5) occurrences за сесію, тож одна повторювана помилка не затопить вашу квоту.


Формат передачі та типи даних

Payloadʼи кодуються у protobuf (proto3) і POSTяться як application/x-protobuf. Енкодер саморобний і без залежностей — жодного protobufjs, тож споживачам не потрібні ні Vite optimizeDeps, ні CJS-interop-конфіг.

Схема (номери полів визначальні — вони мусять збігатися з декодером API):

message Breadcrumb {
  string type      = 1;
  string category  = 2;
  string message   = 3;
  string level     = 4;
  string timestamp = 5;
  string data      = 6;  // обʼєкт у вигляді JSON-рядка
}

message Error {
  string message           = 1;
  string stack             = 2;
  string source            = 3;
  string url               = 4;
  string route             = 5;
  string userId            = 6;  // per-error override (цим клієнтом не використовується)
  string appVersion        = 7;  // per-error override (цим клієнтом не використовується)
  string device            = 8;  // per-error override (цим клієнтом не використовується)
  string occurredAt        = 9;
  repeated Breadcrumb breadcrumbs = 10;
  string level             = 11;
}

message Meta  { string device = 1; string userId = 2; string appVersion = 3; }
message Batch { Meta meta = 1; repeated Error errors = 2; }

device і breadcrumb data — обʼєкти, тож їдуть як JSON-рядки всередині protobuf. Порожні рядки опускаються (дефолт proto3). Бінарне обрамлення лише тримає мережеву панель охайною — це не шифрування; схема публічна, тож будь-хто з нею може декодувати payload.

Як передається

  • Звичайний шлях: fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-protobuf', 'X-Public-Key': <ключ> }, body: <bytes>, keepalive: true }).
  • Шлях page-hide: черга примусово скидається через `navigator.sendBeacon(endpoint
    • '?key=<ключ>', Blob)— оскільки beacon не може ставити заголовки, ключ їде в query-параметрі?key=. Відкат до fetch(..., { keepalive: true }), якщо sendBeacon` недоступний чи відмовив.

API також приймає звичайний JSON на тому самому endpoint (та сама валідація), що зручно для скриптових тестових POSTів, але SDK завжди шле protobuf.


Перегляд і контроль ваших логів

Сенс власного endpoint: після відправки пакетом ви володієте даними і керуєте ними повністю зі свого дашборда — без сторонньої консолі.

  • Перегляд — відкрийте Logs на проєкті, щоб побачити групи помилок, кожну з повідомленням, лічильником, first/last seen, зачепленими routes і стек-трейсом + breadcrumb-ланцюжком на кожну occurrence (включно з захопленими fetch payload/response, коли captureFetchDetails увімкнено).
  • Дедуплікація — API групує occurrences за fingerprint (хеш нормалізованого повідомлення + верхні стек-фрейми), тож повторювана помилка — це один рядок із лічильником, а не тисячі дублікатів.
  • Rate-ліміт і origins — кожен проєкт має власний per-minute rate-ліміт і allowlist origins. Звузьте origins, щоб відкидати сторонній трафік; самого ключа недостатньо, щоб дані зайшли з неперелічeного origin.
  • Retention — occurrences видаляються після вікна retention (за замовчуванням 7 днів на сервері), тож сховище лишається обмеженим без жодних дій з вашого боку.

Оскільки ключ — лише на запис, а читання під логіном, публікація ключа у клієнтському бандлі не відкриває жодних збережених даних.


Приватність

Click-breadcrumbs записують елемент (tag / id / class / короткий текст / data-* атрибути) — ніколи значення полів. Нічого не захоплюється, доки не станеться помилка; breadcrumbs живуть лише в памʼяті і їдуть прикріпленими до помилки.

Значення полів захоплюються лише коли ви явно вмикаєте captureInputs: true. Навіть тоді чутливі поля маскуються (зберігаються як [masked, N chars], ніколи у відкритому вигляді): будь-який type="password", а також поля, чиї name / id / autocomplete збігаються з pass, secret, token, otp, cvv, card, iban, ssn, pin, auth тощо. Нечутливі значення обрізаються до 100 символів.

Захоплення деталей fetch (captureFetchDetails, увімкнено за замовчуванням) редагує чутливі заголовки запиту/відповіді (authorization, cookie, x-api-key, CSRF-токени, …) і обрізає тіла до 2 КБ. Поставте false, якщо не хочете, щоб payloadʼи запитів чи тіла відповідей взагалі покидали браузер.


Ліцензія

PolyForm Shield 1.0.0 — source-available. Безкоштовно ставити й використовувати для будь-якої мети, окрім створення продукту, що конкурує з цим ПЗ або з тим, що ліцензіар надає з його допомогою. Не можна форкнути у конкурента. Повні умови у LICENSE; авторські права лишаються за автором.