@eventra_dev/cli-plugin-vue

中文文档
1.3.3发布于 2026/11/14MITTypeScriptCommonJS构建来源已验证近 30 天下载 2075

Eventra CLI plugin — extract track() calls from Vue SFC (.vue) files

原始使用文档
文档目录18 节
  1. Overview
  2. Installation
  3. What gets detected
  4. <script> / <script setup>
  5. <template> — literal event attributes
  6. <template> — dynamic event attributes
  7. External blocks
  8. <template> - calls in handlers and expressions
  9. Props of a component, whatever they are called
  10. watch and external files
  11. Scripts in JSX, and linked files that are not there
  12. Templates in other languages
  13. Nuxt
  14. Configuration
  15. Plugin contract
  16. Requirements
  17. Test Coverage
  18. License

Eventra CLI Plugin — Vue

npm version npm downloads tests passing coverage node TypeScript license

Official Eventra CLI plugin — extracts track() calls from Vue Single-File Components (.vue), so eventra sync/check/watch understand Vue and Nuxt code the same way they already understand plain TypeScript.


Overview

The CLI core is framework-agnostic and only walks TypeScript and JavaScript files (.ts, .tsx, .mts, .cts, .js, .jsx, .mjs, .cjs). This plugin teaches it .vue: it parses each SFC with the real Vue compiler (@vue/compiler-sfc) - 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 Vue code without any Vue-specific case in the core engine.

Vue and Nuxt .vue files are handled the same way — Nuxt pages/layouts/components are ordinary Vue SFCs. See Nuxt below for auto-import composables.


Installation

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

Enable it in eventra.json:

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

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


What gets detected

<script> / <script setup>

Handled exactly like a regular .ts file — direct SDK calls, function wrappers, variables, ternaries, cross-file propagation all apply:

<script setup lang="ts">
import { Eventra } from "@eventra_dev/eventra-sdk";

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

tracker.track("checkout.started");
</script>

<script> + <script setup> in the same file are merged in source order. defineProps/defineEmits/defineExpose/defineOptions/withDefaults pass through untouched.

<template> — literal event attributes

<template>
  <Button event="checkout.cta" />
</template>

<template> — dynamic event attributes

<template>
  <Button :event="computedEventName" />
</template>

The expression is copied as-is into the same module scope as the script. If it resolves to a real script-level 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.

External blocks

<script src="./logic.ts"> and <template src="./view.html"> are resolved and read from disk.


<template> - calls in handlers and expressions

Tracking calls written in the template itself are read, not only event attributes:

<template>
  <button @click="() => { open(); trackEvent('plan:cogm_open', { id }) }">Open</button>
  <p>{{ trackEvent('panel:viewed') }}</p>
</template>

Read: @click / v-on handlers (one or several statements, multi-line arrow functions), {{ }} interpolations, the source of v-for (item in items()), dynamic arguments (:[name()], @[event()]) and the expressions of v-bind, v-if, v-else-if, v-show, v-model, v-html and v-text. They are placed in the same module as the script, so a function imported or defined there resolves normally; an argument that comes from a v-for variable is reported as a dynamic occurrence. The loop variables of v-for and v-slot parameters are not code and are skipped; the value of a custom directive (v-focus="x") is left alone.

Props of a component, whatever they are called

The prop does not have to be named event. If a component sends one of its props to a tracking call, every place that uses the component with a value for that prop is an event:

<!-- Button.vue -->
<script setup lang="ts">
import { Eventra } from '@eventra_dev/eventra-sdk'
const tracker = new Eventra({ apiKey: 'YOUR_KEY' })
const props = defineProps<{ analyticsName: string }>()
function onClick() { tracker.track(props.analyticsName) }
</script>
<template><button @click="onClick"><slot /></button></template>

<!-- Page.vue -->
<script setup lang="ts">
import Button from './Button.vue'
</script>
<template><Button analytics-name="checkout.cta">Pay</Button></template>

checkout.cta is found. It works with defineProps<{ ... }>(), defineProps([...]), defineProps({ ... }), withDefaults(...), a props object (const props = defineProps(...)) and a destructuring (const { analyticsName } = defineProps(...)), and also when the template reads the prop by its bare name (@click="tracker.track(analyticsName)"). A prop handed on to another component (<Inner :name="props.analyticsName" />) is followed. Props the component never tracks are not events. A prop that comes from a v-for variable is reported as a dynamic occurrence. A prop named by a reserved word (class, for, default, new) does not break the scan; it is read through the props object (props.class), as a template has to read it too.

Not followed (those components are scanned as before, so nothing is lost, but a prop that only they use is not found):

  • An Options API component whose export default is not the last statement of its <script>, whose props is not written out in the object (props: sharedProps), or whose this is read inside a nested function (an arrow keeps it). A component with props: [...] or props: { ... } and this.x in its methods is followed, with or without defineComponent.
  • v-bind="obj" when obj is not an object the analysis can see into (a call, a parameter of the page); an object written out or held in a const is read, in its place among the props.
  • Components registered by name instead of imported, and dynamic components (<component :is="X">).
  • Nuxt auto-imported components (used with no import): the tag is not matched to its file.
  • A component whose normal <script> has its own export default, an export other than a type in <script setup>, an import after other code, or a src= script.

A value the CLI cannot resolve to a plain string (a v-for variable, a prop of the page itself) is listed under "Dynamic event names" instead of becoming an event, with the reason (env, variable, template, call, expression). The tracking call inside the component itself is listed apart, under "Inside a wrapper", because what it tracks is whatever each caller passes; the callers that pass a literal are still found.

watch and external files

<script src="..."> and <template src="..."> point at other files. eventra sync, check and eventra watch read them, and watch rescans the component when one of those files changes (the plugin tells the CLI which files the component was built from).

Scripts in JSX, and linked files that are not there

A script with lang="tsx" or lang="jsx" is read as TSX, so its JSX is not a syntax error. A <script src> or <template src> whose file does not exist gets a note from the CLI (what it holds is not in the scan). A syntax error in a linked <script src> file is reported against the .vue file with the line of the linked file.

Templates in other languages

A <template lang="pug"> (or jade, haml, slm) is not HTML markup and is not read: the plugin returns a note that the CLI prints after a scan, and the file's <script> is read as usual. An empty event="" attribute in a template is skipped without a note. v-memo is read like v-if and the other directives that hold code.

Nuxt

Nuxt pages, layouts, and components are ordinary .vue SFCs — parsed identically, no extra configuration needed.

Composables auto-imported without an explicit import statement (Nuxt's own composables, or your own from composables//utils/) are intended to resolve once the project has run nuxt prepare/nuxt dev (so .nuxt/ exists and is wired into tsconfig.json - the CLI analyzes the project's real tsconfig.json, so Nuxt's generated ambient types are visible to it like any other TypeScript project). The host CLI's resolver understands the declare const x: typeof import("./module")["name"] shape Nuxt/unplugin-auto-import generate for these bindings (covered by a unit test with a hand-written fixture of that ambient shape, and verified manually end to end on a real Nuxt 3 project: after nuxt prepare, calls to an auto-imported composable that wraps track() were detected with no explicit import; without .nuxt/ the same project yields no events). The end-to-end check is manual, not part of the automated test suite.


Configuration

No plugin-specific config — it activates purely by being listed in eventra.json's plugins array (see Installation).


Plugin contract

export interface CliPluginVue {
  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 }>;
    notes?: string[];      // e.g. a `<template lang="pug">` that is not read, a `src=` file that is not there
    dependsOn?: string[];  // `<script src>` / `<template src>` files, so `watch` rescans the component
  }>;
}

No dependency on @eventra_dev/eventra-cli - the CLI adapts this shape internally. .vue → one virtual .vue.ts module (compiled script content, then a function wrapping synthetic calls for every template event="..." binding and the handlers, interpolations and directive expressions copied from the template, under a // --- vue template (auto-generated) --- comment the CLI uses to tell generated code from your own lines). 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-cli as 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.

164 unit tests (vitest), covering:

AreaCovers
SFC parsingScript + script-setup merge order, comment safety, src= external files
Template — literalNested elements, v-if/v-for, slots, multiple template roots
Template — dynamicRaw expression passthrough, resolution through the merged script scope
Script-setup macrosAll five compiler macros (defineProps/defineEmits/defineExpose/defineOptions/withDefaults) pass through without special-casing
Component propsdefineProps in every spelling, props read through an object, a destructuring and bare template names, child components called with their props, name matching of tags to imports
Virtual module outputSingle combined .vue.ts, export stub when script/template are empty
Plugin contractmatch(), includeGlobs, staticSinks, transform()

The Nuxt ambient auto-import shape (declare const x: typeof import(...)) is covered by a unit test in the host CLI that hand-writes that shape. A real nuxt prepare project was also checked end to end by hand, but that check is not part of the automated suite (see the Nuxt section above).

Run locally:

pnpm --filter @eventra_dev/cli-plugin-vue test
pnpm --filter @eventra_dev/cli-plugin-vue test:coverage

License

MIT, copyright (c) 2026 Yuriy Korolik. See LICENSE.

版本与发布记录

@eventra_dev/cli-plugin-vue 共发布 21 个版本,首次发布于 2026/07/23;过去 12 个月发布了 21 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.3.3latest2026/11/14今天
1.3.22026/11/104 天前
1.3.12026/11/104 天前
1.3.02026/11/0410 天前
1.2.52026/11/0112 天前
1.2.42026/10/2916 天前

关于 @eventra_dev/cli-plugin-vue 的常见问题

@eventra_dev/cli-plugin-vue 是什么?

Eventra CLI plugin — extract track() calls from Vue SFC (.vue) files

如何安装 @eventra_dev/cli-plugin-vue?

在项目目录运行 npm install @eventra_dev/cli-plugin-vue,或使用 pnpm add / yarn add / bun add。

@eventra_dev/cli-plugin-vue 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@eventra_dev/cli-plugin-vue 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@eventra_dev/cli-plugin-vue 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@eventra_dev/cli-plugin-vue 可以商用吗?

@eventra_dev/cli-plugin-vue 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@eventra_dev/cli-plugin-vue 的下载量有多少?

根据 npm 官方下载统计,@eventra_dev/cli-plugin-vue 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,075 次,日均约 69 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@eventra_dev/cli-plugin-vue 还在维护吗?

最新版本 1.3.3 发布于 2026/11/14(今天);至今共发布 21 个版本,其中过去 12 个月发布了 21 个;首次发布于 2026/07/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。