@eventra_dev/cli-plugin-astro
v1.0.2
Published
Eventra CLI plugin — extract track() calls from Astro (.astro) files
Maintainers
Readme
Eventra CLI Plugin — Astro
Official Eventra CLI plugin — extracts track() calls from Astro components (.astro), so eventra sync/check/watch understand Astro code the same way they already understand plain TypeScript.
Overview
The CLI core is framework-agnostic and only walks .ts/.tsx/.js/.jsx. This plugin teaches it .astro: it parses each component with the real Astro compiler (@astrojs/compiler) — not a regex — and hands the CLI a single virtual TypeScript module per file, so every existing detection rule (direct SDK calls, function wrappers, cross-file propagation, dynamic-name reporting) applies to Astro code without any Astro-specific case in the core engine.
Installation
npm install -D @eventra_dev/cli-plugin-astro @eventra_dev/eventra-cli
# or
pnpm add -D @eventra_dev/cli-plugin-astro @eventra_dev/eventra-cliEnable it in eventra.json:
{
"plugins": ["@eventra_dev/cli-plugin-astro"],
"sync": {
"include": ["**/*.{ts,tsx,js,jsx}"],
"exclude": ["node_modules", "dist", ".astro", ".git"]
}
}sync.include does not need **/*.astro added manually — the plugin registers it via includeGlobs.
What gets detected
Frontmatter
Handled exactly like a regular .ts file — direct SDK calls, function wrappers, variables, ternaries, cross-file propagation all apply. Astro frontmatter is TypeScript already, so there's no lang= attribute to detect:
---
import { Eventra } from "@eventra_dev/eventra-sdk";
const tracker = new Eventra({ apiKey: "YOUR_PROJECT_API_KEY" });
tracker.track("checkout.started");
---Template — literal event attributes
<button event="checkout.cta">Pay</button>Template — dynamic event attributes
<button event={computedEventName}>Pay</button>
<!-- JSX shorthand also works: {event} is sugar for event={event} -->
<button {event} />The expression is copied as-is into the same module scope as the frontmatter. If it resolves to a real frontmatter constant, the event name is detected normally; otherwise it's reported as a dynamic occurrence (same mechanism as tracker.track(someVariable) in plain TypeScript) instead of being silently dropped.
event is recognized on any tag — plain elements, components, custom elements, and fragments — including ones nested inside JSX expressions ({cond && <Button event="..." />}, {items.map((item) => <Button event="..." />)}), since the plugin walks the whole template rather than special-casing specific expression shapes.
Configuration
No plugin-specific config — it activates purely by being listed in eventra.json's plugins array (see Installation).
Plugin contract
export interface CliPluginAstro {
readonly id: string;
readonly version: string;
readonly includeGlobs: readonly string[];
readonly staticSinks?: readonly CliPluginStaticCalleeSink[];
match(path: string): boolean;
transform(input: { path: string; source: string }): Promise<{
modules: Array<{ path: string; content: string }>;
}>;
}No dependency on @eventra_dev/eventra-cli — the CLI adapts this shape internally. .astro → one virtual .astro.ts module (frontmatter content, then a function wrapping synthetic calls for every template event="..." binding). staticSinks describes those synthetic calls; the CLI builds its own sink detector from them. See @eventra_dev/eventra-cli's plugin docs for the full external-plugin contract.
Requirements
- Node.js 18+
@eventra_dev/eventra-clias the host CLI
Test Coverage
100% statement/branch/function/line coverage (v8 provider, pnpm test:coverage), enforced via a coverage.thresholds block in vitest.config.ts.
21 unit tests (vitest), covering:
| Area | Covers |
|---|---|
| Component parsing | Frontmatter extraction, comment safety, compiler-diagnostic reporting |
| Template — literal | Nested elements, JSX expressions (&&, ternary, .map()) |
| Template — dynamic | Raw expression passthrough, {event} shorthand, resolution through the frontmatter scope |
| Edge cases | Empty event="", boolean-shorthand event, empty event={}, unbraced template-literal event=`a-${b}` (unsupported — silently ignored, same as any other interpolated/mixed value; wrap it in braces, event={`a-${b}`}, to make it a supported dynamic expression) |
| Astro globals | Astro.props destructuring passes through without special-casing |
| Virtual module output | Single combined .astro.ts, export stub when frontmatter/template are empty |
| Plugin contract | match(), includeGlobs, staticSinks, transform() |
Run locally:
pnpm --filter @eventra_dev/cli-plugin-astro test
pnpm --filter @eventra_dev/cli-plugin-astro test:coverageLicense
MIT
