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

@eventra_dev/eventra-cli

v1.0.2

Published

Static analytics event extraction CLI powered by the TypeScript compiler API

Readme

Eventra CLI

Eventra CLI statically discovers analytics events from @eventra_dev/eventra-sdk usage in your codebase — including function wrappers and cross-file propagation chains.


Overview

The CLI scans TypeScript and JavaScript with the TypeScript compiler API and extracts only calls to Eventra.prototype.track() on instances of Eventra imported from @eventra_dev/eventra-sdk.

It does not detect generic track(), Segment, Google Analytics, or other libraries out of the box. Framework files (e.g. .vue) require an optional plugin.


Installation

npm install -D @eventra_dev/eventra-cli
# or
pnpm add -D @eventra_dev/eventra-cli

Your project should use the runtime SDK:

pnpm add @eventra_dev/eventra-sdk

Quick Start

eventra init
eventra sync
eventra check
eventra send

What gets detected

Direct SDK calls

import { Eventra } from "@eventra_dev/eventra-sdk";

const tracker = new Eventra({ apiKey: "YOUR_PROJECT_API_KEY" });

tracker.track("checkout.completed");
tracker.track("app.loaded", { userId: "user_123" });
tracker?.track("optional.chain");

Function wrappers (propagation)

Wrappers that call Eventra.track() inside are registered automatically:

function trackFeature(name: string) {
  sdk.track(name);
}

trackFeature("purchase");

Variables, templates, conditionals

const EVENT = "signup";
tracker.track(EVENT);

tracker.track(`feature_${type}`);

tracker.track(flag ? "path.a" : "path.b");

Cross-file

// tracker.ts
export function trackFeature(name: string) {
  client.track(name);
}

// app.ts
import { trackFeature } from "./tracker";
trackFeature("purchase");

Event name rules (aligned with SDK)

| Rule | Limit | |------|--------| | Max length | 64 characters (same as SDK) | | Allowed characters | a-zA-Z0-9:_./- | | Position | First argument of .track(name, options?) |

The second argument (userId, properties) is not used as the event name.


What is ignored

// Not from @eventra_dev/eventra-sdk
track("legacy");
analytics.track("ga");
segment.track("x");

// Wrong API shape for SDK (object as first argument)
tracker.track({ event: "click" });

Commands

eventra sync

Full project scan → updates eventra.json:

  • events — discovered event names
  • functionWrappers — detected wrapper functions

eventra check

Compares config with the current scan (events + wrappers). Exit code 1 on drift.

eventra check --fix

Writes scan results into eventra.json.

eventra watch

Incremental scan with the same rules as sync.

eventra send

Uploads events from config to the Eventra API. Requires apiKey (and optionally endpoint) in eventra.json. Events are POSTed to POST /api/v1/cli/events and marked as non-billable on the backend.

Network resilience:

  • Up to 4 attempts with exponential backoff + jitter (capped at 8 s)
  • Retries on 429 and 5xx responses, and on transport errors (timeout / DNS / connection reset)
  • Permanent failure (4xx other than 429) surfaces immediately without retry
  • 10 s timeout per attempt via AbortController

Plugins

The CLI core is framework-agnostic. Extensions are separate npm packages with their own types — the CLI loads them from eventra.json and adapts their output internally.

Vue (.vue SFC)

Install the official Vue plugin and enable it in config:

pnpm add -D @eventra_dev/cli-plugin-vue
{
  "plugins": ["@eventra_dev/cli-plugin-vue"],
  "sync": {
    "include": ["**/*.{ts,tsx,js,jsx}"],
    "exclude": ["node_modules", "dist", ".next", ".git"]
  }
}

The plugin:

  • splits each .vue file into virtual TypeScript modules (App.vue.ts, App.vue.template.ts)
  • extracts track() calls from <script> blocks
  • detects static event="feature_name" attributes in <template> (literals only)

sync.include does not need **/*.vue manually — the plugin registers **/*.vue via includeGlobs.

Before publishing / local development

Plugins are resolved from your project's node_modules (same as any dependency):

{
  "devDependencies": {
    "@eventra_dev/cli-plugin-vue": "file:../cli-plugin-vue"
  }
}

The plugin package must be built (dist/) before use. Unpublished plugins work the same way — only the install source differs.

Plugin contract (for authors)

External plugins export an object (or factory) with:

| Field | Purpose | |-------|---------| | id | Unique preprocessor name | | includeGlobs | Extra glob patterns merged into the scan | | match(path) | Whether this plugin handles a file | | transform({ path, source }) | Returns { modules: [{ path, content }] } | | staticSinks? | Declarative callee-based sink rules (CLI converts to internal detectors) |

No dependency on @eventra_dev/eventra-cli is required. See ARCHITECTURE.md for details.


Configuration

{
  "apiKey": "",
  "endpoint": "",
  "events": [],
  "functionWrappers": [],
  "plugins": [],
  "sync": {
    "include": ["**/*.{ts,tsx,js,jsx}"],
    "exclude": ["node_modules", "dist", ".next", ".git"]
  }
}

| Field | Description | |-------|-------------| | plugins | Module specifiers to import() at startup (e.g. @eventra_dev/cli-plugin-vue) | | sync.include | Base glob patterns; plugin includeGlobs are merged automatically | | sync.exclude | Paths skipped during scan |


How it works

  1. Load built-in plugins (eventra-sdk sink detector) and any packages listed in plugins.
  2. Glob project files (sync.include + plugin includeGlobs).
  3. Run file preprocessors (e.g. .vue → virtual .ts modules).
  4. Load sources into an incremental TypeScript program (with SDK type shim).
  5. Phase 1 — find Eventra instances from @eventra_dev/eventra-sdk and register function wrappers that call .track().
  6. Phase 2 — resolve static event names and wrapper propagation chains (sink detector chain includes plugin sinks).
  7. Write results to eventra.json.

watch tracks disk source files (including .vue), re-runs preprocessors on change, and incrementally updates the engine.

No runtime execution. No monkey-patching.


Requirements

  • Node.js 18+
  • TypeScript/JavaScript source using @eventra_dev/eventra-sdk

Test Coverage

Two test layers, 59 unit tests + 12 e2e fixtures + 3 check exit-code scenarios.

Unit tests (vitest) — 13 suites covering core modules:

| Module | Covers | |---|---| | ImportGraph | Forward/reverse edges, cycles, stale-edge cleanup, file removal | | Scheduler | Batch coalescing, last-write-wins per file, sequential bursts, error propagation | | DocumentRegistry | Path normalization, version bumping, no-op on identical content, ensure() from disk | | CompilerContext | Stage/update/remove files, resolveModule with tsconfig.json paths, source-file enumeration | | EventraEngine | Direct calls, SDK isolation, cross-file wrappers, file updates, file removal, wrapper filtering | | PluginRegistry | Built-in SDK sink, preprocessors, virtual-path mapping, include-pattern dedup | | external plugin adapter | Transform output mapping, static sink registration, invalid result rejection | | vue-shaped external plugin | Adapter path for script + template virtual modules and staticSinks | | processFile | Script-kind detection, import/export specifier extraction | | extractTemplateExpressions | Vue/Svelte/Astro attribute patterns | | normalizeConfig | Sort events, dedupe wrappers, defaults, preserve apiKey / endpoint / sync / plugins | | buildConfigFromScan | Replace events + wrappers, preserve everything else | | hash | Stability and uniqueness |

End-to-end fixtures — 12 isolated TS projects scanned via eventra sync:

| Fixture | Covers | |---|---| | sdk/direct | Plain tracker.track() calls | | frontend/react, frontend/next, frontend/vue | Framework-specific code shapes | | backend/node, backend/express, backend/nest | Backend wrappers and middleware chains | | wrappers/function | Local wrapper functions, methods, objects, ternaries, templates | | wrappers/barrel | export * from "./tracker" re-exports | | wrappers/default-export | export default function trackFeature propagation | | wrappers/path-aliases | tsconfig.json paths mapping (@app/*) | | watch-incremental | Engine state across sequential file updates (matches sync output) |

eventra check exit-code scenarios:

  • Drift → exit 1
  • --fix writes scan results into eventra.json → exit 0
  • Parity (no drift) → exit 0

Run locally:

pnpm --filter @eventra_dev/eventra-cli test       # unit + e2e + exit codes
pnpm --filter @eventra_dev/eventra-cli test:unit  # vitest only
pnpm --filter @eventra_dev/eventra-cli test:e2e   # fixtures + check exit codes

License

MIT