@eventra_dev/eventra-cli 0.3.6 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -185
- package/dist/analysis/engine/analyzeFile.js +12 -0
- package/dist/analysis/extractor/extractor.js +4 -5
- package/dist/analysis/extractor/propagationExtractor.js +4 -5
- package/dist/analysis/resolver/callResolver.js +4 -0
- package/dist/analysis/resolver/exportResolver.js +3 -0
- package/dist/analysis/scanner/scanner.js +1 -1
- package/dist/analysis/scanner/sinkDetector.js +17 -37
- package/dist/analysis/sdk/eventraSdk.js +42 -0
- package/dist/analysis/sdk/isEventraTrackCall.js +171 -0
- package/dist/analysis/shared/eventValidation.js +7 -0
- package/dist/analysis/symbols/wrapperRegistry.js +9 -15
- package/dist/cli/check.js +29 -47
- package/dist/cli/init.js +5 -6
- package/dist/cli/sync.js +5 -3
- package/dist/cli/watch.js +27 -33
- package/dist/compiler/compilerContext.js +71 -49
- package/dist/config/config.js +13 -2
- package/dist/core/EventraEngine.js +89 -37
- package/dist/core/projectScanner.js +13 -12
- package/dist/core/scanResults.js +18 -0
- package/dist/index.js +5 -1
- package/package.json +2 -2
- package/dist/analysis/engine/recursiveWrapperAnalyzer.js +0 -76
package/README.md
CHANGED
|
@@ -9,17 +9,15 @@
|
|
|
9
9
|
[](https://www.typescriptlang.org/)
|
|
10
10
|
[]()
|
|
11
11
|
|
|
12
|
-
Eventra CLI
|
|
12
|
+
Eventra CLI statically discovers analytics events from [**@eventra_dev/eventra-sdk**](https://www.npmjs.com/package/@eventra_dev/eventra-sdk) usage in your codebase — including function wrappers and cross-file propagation chains.
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
## Overview
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
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`.
|
|
19
19
|
|
|
20
|
-
It
|
|
21
|
-
|
|
22
|
-
No runtime instrumentation required.
|
|
20
|
+
It does **not** detect generic `track()`, Segment, Google Analytics, or other libraries.
|
|
23
21
|
|
|
24
22
|
---
|
|
25
23
|
|
|
@@ -31,6 +29,12 @@ npm install -D @eventra_dev/eventra-cli
|
|
|
31
29
|
pnpm add -D @eventra_dev/eventra-cli
|
|
32
30
|
```
|
|
33
31
|
|
|
32
|
+
Your project should use the runtime SDK:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pnpm add @eventra_dev/eventra-sdk
|
|
36
|
+
```
|
|
37
|
+
|
|
34
38
|
---
|
|
35
39
|
|
|
36
40
|
## Quick Start
|
|
@@ -44,180 +48,108 @@ eventra send
|
|
|
44
48
|
|
|
45
49
|
---
|
|
46
50
|
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
1. Parses your project using the TypeScript compiler API
|
|
50
|
-
2. Builds semantic indexes from AST nodes
|
|
51
|
-
3. Resolves wrappers, imports, exports, and propagation chains
|
|
52
|
-
4. Extracts concrete analytics events statically
|
|
53
|
-
5. Incrementally re-analyzes only affected files
|
|
54
|
-
|
|
55
|
-
No runtime SDK hooks.
|
|
56
|
-
No Babel transforms.
|
|
57
|
-
No instrumentation.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## Why Eventra
|
|
62
|
-
|
|
63
|
-
* Prevent missing or inconsistent event tracking
|
|
64
|
-
* Keep analytics schemas synchronized with source code
|
|
65
|
-
* Detect dead or unused events
|
|
66
|
-
* Analyze wrapper-heavy codebases statically
|
|
67
|
-
* Integrate validation into CI/CD pipelines
|
|
68
|
-
* Avoid runtime analytics overhead
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## Commands
|
|
73
|
-
|
|
74
|
-
### `eventra init`
|
|
75
|
-
|
|
76
|
-
Creates `eventra.json` configuration file.
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
### `eventra sync`
|
|
81
|
-
|
|
82
|
-
Scans your project and updates the list of detected events.
|
|
51
|
+
## What gets detected
|
|
83
52
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
##### Direct calls
|
|
53
|
+
### Direct SDK calls
|
|
87
54
|
|
|
88
55
|
```ts
|
|
89
|
-
|
|
90
|
-
analytics.track("event")
|
|
91
|
-
```
|
|
56
|
+
import { Eventra } from "@eventra_dev/eventra-sdk";
|
|
92
57
|
|
|
93
|
-
|
|
58
|
+
const tracker = new Eventra({ apiKey: "YOUR_PROJECT_API_KEY" });
|
|
94
59
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
track(
|
|
60
|
+
tracker.track("checkout.completed");
|
|
61
|
+
tracker.track("app.loaded", { userId: "user_123" });
|
|
62
|
+
tracker?.track("optional.chain");
|
|
98
63
|
```
|
|
99
64
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
track(EVENTS.CLICK)
|
|
104
|
-
```
|
|
65
|
+
### Function wrappers (propagation)
|
|
105
66
|
|
|
106
|
-
|
|
67
|
+
Wrappers that call `Eventra.track()` inside are registered automatically:
|
|
107
68
|
|
|
108
69
|
```ts
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
##### Conditional expressions
|
|
70
|
+
function trackFeature(name: string) {
|
|
71
|
+
sdk.track(name);
|
|
72
|
+
}
|
|
113
73
|
|
|
114
|
-
|
|
115
|
-
track(condition ? "a" : "b")
|
|
74
|
+
trackFeature("purchase");
|
|
116
75
|
```
|
|
117
76
|
|
|
118
|
-
|
|
77
|
+
### Variables, templates, conditionals
|
|
119
78
|
|
|
120
79
|
```ts
|
|
121
|
-
|
|
122
|
-
|
|
80
|
+
const EVENT = "signup";
|
|
81
|
+
tracker.track(EVENT);
|
|
123
82
|
|
|
124
|
-
|
|
83
|
+
tracker.track(`feature_${type}`);
|
|
125
84
|
|
|
126
|
-
|
|
127
|
-
track({
|
|
128
|
-
event: "click"
|
|
129
|
-
})
|
|
85
|
+
tracker.track(flag ? "path.a" : "path.b");
|
|
130
86
|
```
|
|
131
87
|
|
|
132
|
-
|
|
88
|
+
### Cross-file
|
|
133
89
|
|
|
134
90
|
```ts
|
|
135
|
-
|
|
136
|
-
|
|
91
|
+
// tracker.ts
|
|
92
|
+
export function trackFeature(name: string) {
|
|
93
|
+
client.track(name);
|
|
137
94
|
}
|
|
138
95
|
|
|
139
|
-
|
|
96
|
+
// app.ts
|
|
97
|
+
import { trackFeature } from "./tracker";
|
|
98
|
+
trackFeature("purchase");
|
|
140
99
|
```
|
|
141
100
|
|
|
142
|
-
|
|
101
|
+
---
|
|
143
102
|
|
|
144
|
-
|
|
145
|
-
function trackEvent(props: {
|
|
146
|
-
event: string
|
|
147
|
-
}) {
|
|
148
|
-
track(props.event)
|
|
149
|
-
}
|
|
103
|
+
## Event name rules (aligned with SDK)
|
|
150
104
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
105
|
+
| Rule | Limit |
|
|
106
|
+
|------|--------|
|
|
107
|
+
| Max length | **64 characters** (same as SDK) |
|
|
108
|
+
| Allowed characters | `a-zA-Z0-9:_./-` |
|
|
109
|
+
| Position | First argument of `.track(name, options?)` |
|
|
155
110
|
|
|
156
|
-
|
|
111
|
+
The second argument (`userId`, `properties`) is **not** used as the event name.
|
|
157
112
|
|
|
158
|
-
|
|
159
|
-
function buildEvent(name: string) {
|
|
160
|
-
return name
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
track(buildEvent("signup"))
|
|
164
|
-
```
|
|
113
|
+
---
|
|
165
114
|
|
|
166
|
-
|
|
115
|
+
## What is ignored
|
|
167
116
|
|
|
168
117
|
```ts
|
|
169
|
-
|
|
118
|
+
// Not from @eventra_dev/eventra-sdk
|
|
119
|
+
track("legacy");
|
|
120
|
+
analytics.track("ga");
|
|
121
|
+
segment.track("x");
|
|
170
122
|
|
|
171
|
-
|
|
123
|
+
// Wrong API shape for SDK (object as first argument)
|
|
124
|
+
tracker.track({ event: "click" });
|
|
172
125
|
```
|
|
173
126
|
|
|
174
127
|
---
|
|
175
128
|
|
|
176
|
-
|
|
129
|
+
## Commands
|
|
177
130
|
|
|
178
|
-
|
|
131
|
+
### `eventra sync`
|
|
179
132
|
|
|
180
|
-
|
|
181
|
-
eventra check
|
|
182
|
-
```
|
|
133
|
+
Full project scan → updates `eventra.json`:
|
|
183
134
|
|
|
184
|
-
|
|
135
|
+
- `events` — discovered event names
|
|
136
|
+
- `functionWrappers` — detected wrapper functions
|
|
185
137
|
|
|
186
|
-
|
|
187
|
-
* Removed events
|
|
188
|
-
* Invalid or inconsistent tracking usage
|
|
138
|
+
### `eventra check`
|
|
189
139
|
|
|
190
|
-
|
|
140
|
+
Compares config with the current scan (events + wrappers). Exit code `1` on drift.
|
|
191
141
|
|
|
192
142
|
### `eventra check --fix`
|
|
193
143
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
eventra check --fix
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
---
|
|
144
|
+
Writes scan results into `eventra.json`.
|
|
201
145
|
|
|
202
146
|
### `eventra watch`
|
|
203
147
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
```bash
|
|
207
|
-
eventra watch
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
Only affected files are re-analyzed after changes.
|
|
211
|
-
|
|
212
|
-
---
|
|
148
|
+
Incremental scan with the same rules as `sync`.
|
|
213
149
|
|
|
214
150
|
### `eventra send`
|
|
215
151
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
```bash
|
|
219
|
-
eventra send
|
|
220
|
-
```
|
|
152
|
+
Uploads `events` from config to the Eventra API.
|
|
221
153
|
|
|
222
154
|
---
|
|
223
155
|
|
|
@@ -228,79 +160,31 @@ eventra send
|
|
|
228
160
|
"apiKey": "",
|
|
229
161
|
"endpoint": "",
|
|
230
162
|
"events": [],
|
|
231
|
-
"wrappers": [],
|
|
232
163
|
"functionWrappers": [],
|
|
233
164
|
"sync": {
|
|
234
165
|
"include": ["**/*.{ts,tsx,js,jsx}"],
|
|
235
|
-
"exclude": [
|
|
236
|
-
"node_modules",
|
|
237
|
-
"dist",
|
|
238
|
-
".next",
|
|
239
|
-
".git"
|
|
240
|
-
]
|
|
166
|
+
"exclude": ["node_modules", "dist", ".next", ".git"]
|
|
241
167
|
}
|
|
242
168
|
}
|
|
243
169
|
```
|
|
244
170
|
|
|
245
171
|
---
|
|
246
172
|
|
|
247
|
-
##
|
|
248
|
-
|
|
249
|
-
### Semantic propagation analysis
|
|
250
|
-
|
|
251
|
-
Eventra resolves event propagation through wrappers and returned values.
|
|
252
|
-
|
|
253
|
-
```ts
|
|
254
|
-
function createEvent(name: string) {
|
|
255
|
-
return name
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function trackEvent(name: string) {
|
|
259
|
-
track(createEvent(name))
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
### Incremental analysis engine
|
|
266
|
-
|
|
267
|
-
Eventra does NOT rescan the whole project after every update.
|
|
268
|
-
|
|
269
|
-
Instead it:
|
|
270
|
-
|
|
271
|
-
1. Updates changed files
|
|
272
|
-
2. Invalidates affected caches
|
|
273
|
-
3. Rebuilds TypeScript incrementally
|
|
274
|
-
4. Traverses dependency graph
|
|
275
|
-
5. Re-analyzes affected files only
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
### Static extraction
|
|
280
|
-
|
|
281
|
-
Eventra works entirely statically.
|
|
282
|
-
|
|
283
|
-
No runtime execution.
|
|
284
|
-
No monkey patching.
|
|
285
|
-
No SDK instrumentation.
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## Supported Environments
|
|
173
|
+
## How it works
|
|
290
174
|
|
|
291
|
-
|
|
175
|
+
1. Load project files into an incremental TypeScript program (with SDK type shim).
|
|
176
|
+
2. **Phase 1** — find `Eventra` instances from `@eventra_dev/eventra-sdk` and register function wrappers that call `.track()`.
|
|
177
|
+
3. **Phase 2** — resolve static event names and wrapper propagation chains.
|
|
178
|
+
4. Write results to `eventra.json`.
|
|
292
179
|
|
|
293
|
-
|
|
294
|
-
* TypeScript
|
|
295
|
-
* Node.js projects
|
|
296
|
-
* Browser applications
|
|
297
|
-
* Monorepos
|
|
180
|
+
No runtime execution. No monkey-patching.
|
|
298
181
|
|
|
299
182
|
---
|
|
300
183
|
|
|
301
184
|
## Requirements
|
|
302
185
|
|
|
303
|
-
|
|
186
|
+
- Node.js 18+
|
|
187
|
+
- TypeScript/JavaScript source using `@eventra_dev/eventra-sdk`
|
|
304
188
|
|
|
305
189
|
---
|
|
306
190
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.indexSourceFile = indexSourceFile;
|
|
4
|
+
exports.extractFromIndex = extractFromIndex;
|
|
5
|
+
const scanner_1 = require("../scanner/scanner");
|
|
6
|
+
const extractor_1 = require("../extractor/extractor");
|
|
7
|
+
function indexSourceFile(source, checker, wrapperRegistry) {
|
|
8
|
+
return (0, scanner_1.scanSource)(source, checker, wrapperRegistry);
|
|
9
|
+
}
|
|
10
|
+
function extractFromIndex(index, config, checker, wrapperRegistry, evaluationCache, resolvedCallCache, returnPropagationCache, resolvedExportCache) {
|
|
11
|
+
return (0, extractor_1.extractEvents)(index, checker, config, evaluationCache, resolvedExportCache, resolvedCallCache, returnPropagationCache, wrapperRegistry);
|
|
12
|
+
}
|
|
@@ -8,9 +8,7 @@ const typescript_1 = __importDefault(require("typescript"));
|
|
|
8
8
|
const resolver_1 = require("../resolver/resolver");
|
|
9
9
|
const evaluationContext_1 = require("../shared/evaluationContext");
|
|
10
10
|
const propagationExtractor_1 = require("./propagationExtractor");
|
|
11
|
-
|
|
12
|
-
return (value.length > 0 && value.length < 160 && /^[a-zA-Z0-9:_./-]+$/.test(value));
|
|
13
|
-
}
|
|
11
|
+
const eventValidation_1 = require("../shared/eventValidation");
|
|
14
12
|
function extractEvents(index, checker, _config, evaluationCache, exportCache, resolvedCallCache, returnPropagationCache, wrapperRegistry) {
|
|
15
13
|
const events = new Set();
|
|
16
14
|
// direct track sinks
|
|
@@ -18,8 +16,9 @@ function extractEvents(index, checker, _config, evaluationCache, exportCache, re
|
|
|
18
16
|
for (const argument of call.trackedArguments) {
|
|
19
17
|
const resolved = (0, resolver_1.resolveNodeValue)(argument, checker, (0, evaluationContext_1.createEvaluationContext)(), new Set(), evaluationCache, resolvedCallCache, returnPropagationCache, exportCache);
|
|
20
18
|
for (const value of resolved.values) {
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const normalized = (0, eventValidation_1.normalizeEventName)(value);
|
|
20
|
+
if (normalized) {
|
|
21
|
+
events.add(normalized);
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
}
|
|
@@ -8,9 +8,7 @@ const typescript_1 = __importDefault(require("typescript"));
|
|
|
8
8
|
const callResolver_1 = require("../resolver/callResolver");
|
|
9
9
|
const resolver_1 = require("../resolver/resolver");
|
|
10
10
|
const evaluationContext_1 = require("../shared/evaluationContext");
|
|
11
|
-
|
|
12
|
-
return (value.length > 0 && value.length < 160 && /^[a-zA-Z0-9:_./-]+$/.test(value));
|
|
13
|
-
}
|
|
11
|
+
const eventValidation_1 = require("../shared/eventValidation");
|
|
14
12
|
function resolveObjectPath(expression, path) {
|
|
15
13
|
let current = expression;
|
|
16
14
|
for (const segment of path) {
|
|
@@ -86,8 +84,9 @@ function extractPropagation(propagation, call, checker, evaluationCache, resolve
|
|
|
86
84
|
}
|
|
87
85
|
const resolved = (0, resolver_1.resolveNodeValue)(propagation.targetNode, checker, context, new Set(), evaluationCache, resolvedCallCache, returnPropagationCache, exportCache);
|
|
88
86
|
for (const value of resolved.values) {
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
const normalized = (0, eventValidation_1.normalizeEventName)(value);
|
|
88
|
+
if (normalized) {
|
|
89
|
+
events.add(normalized);
|
|
91
90
|
}
|
|
92
91
|
}
|
|
93
92
|
}
|
|
@@ -22,6 +22,10 @@ function resolveDeclaration(declaration) {
|
|
|
22
22
|
if (typescript_1.default.isPropertyDeclaration(declaration) && declaration.initializer && isFunctionLike(declaration.initializer)) {
|
|
23
23
|
return declaration.initializer;
|
|
24
24
|
}
|
|
25
|
+
// { trackFeature() {} }
|
|
26
|
+
if (typescript_1.default.isPropertyAssignment(declaration) && declaration.initializer && isFunctionLike(declaration.initializer)) {
|
|
27
|
+
return declaration.initializer;
|
|
28
|
+
}
|
|
25
29
|
return null;
|
|
26
30
|
}
|
|
27
31
|
function getExpressionSymbol(expression, checker) {
|
|
@@ -16,6 +16,9 @@ function isConcreteDeclaration(node) {
|
|
|
16
16
|
|| typescript_1.default.isPropertyDeclaration(node));
|
|
17
17
|
}
|
|
18
18
|
function resolveExportedSymbol(symbol, checker, cache, visited) {
|
|
19
|
+
if (typeof symbol.getDeclarations !== "function") {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
19
22
|
const seen = visited ?? new Set();
|
|
20
23
|
const cached = cache.get(symbol);
|
|
21
24
|
if (cached !== undefined) {
|
|
@@ -23,7 +23,7 @@ function scanSource(source, checker, wrapperRegistry) {
|
|
|
23
23
|
}
|
|
24
24
|
// sink detection
|
|
25
25
|
if (typescript_1.default.isCallExpression(node)) {
|
|
26
|
-
const sink = (0, sinkDetector_1.detectTrackSink)(node);
|
|
26
|
+
const sink = (0, sinkDetector_1.detectTrackSink)(node, checker);
|
|
27
27
|
if (sink) {
|
|
28
28
|
sinks.push(sink);
|
|
29
29
|
const trackedArguments = sink.trackedArguments.map(tracked => {
|
|
@@ -5,53 +5,33 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.detectTrackSink = detectTrackSink;
|
|
7
7
|
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
function isTrackIdentifier(expr) {
|
|
12
|
-
return (typescript_1.default.isIdentifier(expr) && expr.text === "track");
|
|
13
|
-
}
|
|
14
|
-
function isTrackProperty(expr) {
|
|
15
|
-
return (typescript_1.default.isPropertyAccessExpression(expr) && expr.name.text === "track");
|
|
16
|
-
}
|
|
17
|
-
function isOptionalTrackProperty(expr) {
|
|
18
|
-
return (typescript_1.default.isPropertyAccessChain(expr) && expr.name.text === "track");
|
|
19
|
-
}
|
|
8
|
+
const isEventraTrackCall_1 = require("../sdk/isEventraTrackCall");
|
|
9
|
+
/** SDK: track(name: string, options?) — event name is always the first argument. */
|
|
20
10
|
function extractTrackedArguments(call) {
|
|
21
|
-
const result = [];
|
|
22
11
|
if (call.arguments.length === 0) {
|
|
23
|
-
return
|
|
12
|
+
return [];
|
|
24
13
|
}
|
|
25
14
|
const first = call.arguments[0];
|
|
26
15
|
if (typescript_1.default.isObjectLiteralExpression(first)) {
|
|
27
|
-
|
|
28
|
-
if (!typescript_1.default.isPropertyAssignment(property) && !typescript_1.default.isShorthandPropertyAssignment(property)) {
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
const name = property.name.getText();
|
|
32
|
-
if (name !== "event" && name !== "name" && name !== "type") {
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
result.push({
|
|
36
|
-
index: 0,
|
|
37
|
-
propertyPath: [name],
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
return result;
|
|
16
|
+
return [];
|
|
41
17
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
index: 0,
|
|
21
|
+
propertyPath: [],
|
|
22
|
+
},
|
|
23
|
+
];
|
|
47
24
|
}
|
|
48
|
-
function detectTrackSink(call) {
|
|
49
|
-
|
|
50
|
-
|
|
25
|
+
function detectTrackSink(call, checker) {
|
|
26
|
+
if (!(0, isEventraTrackCall_1.isEventraSdkTrackCall)(call, checker)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const trackedArguments = extractTrackedArguments(call);
|
|
30
|
+
if (trackedArguments.length === 0) {
|
|
51
31
|
return null;
|
|
52
32
|
}
|
|
53
33
|
return {
|
|
54
34
|
call,
|
|
55
|
-
trackedArguments
|
|
35
|
+
trackedArguments,
|
|
56
36
|
};
|
|
57
37
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EVENTRA_SDK_SHIM = exports.MAX_EVENT_NAME_LENGTH = exports.EVENTRA_SDK_PACKAGE = void 0;
|
|
4
|
+
exports.isEventraSdkModuleSpecifier = isEventraSdkModuleSpecifier;
|
|
5
|
+
exports.normalizeEventName = normalizeEventName;
|
|
6
|
+
exports.isValidEventName = isValidEventName;
|
|
7
|
+
/** Mirrors @eventra_dev/eventra-sdk runtime limits (see packages/sdk/src/client.ts). */
|
|
8
|
+
exports.EVENTRA_SDK_PACKAGE = "@eventra_dev/eventra-sdk";
|
|
9
|
+
exports.MAX_EVENT_NAME_LENGTH = 64;
|
|
10
|
+
function isEventraSdkModuleSpecifier(specifier) {
|
|
11
|
+
const normalized = specifier.replace(/\\/g, "/");
|
|
12
|
+
return (normalized === exports.EVENTRA_SDK_PACKAGE ||
|
|
13
|
+
normalized.startsWith(`${exports.EVENTRA_SDK_PACKAGE}/`));
|
|
14
|
+
}
|
|
15
|
+
function normalizeEventName(value) {
|
|
16
|
+
const trimmed = value.trim();
|
|
17
|
+
if (!trimmed || trimmed.length > exports.MAX_EVENT_NAME_LENGTH) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
if (!/^[a-zA-Z0-9:_./-]+$/.test(trimmed)) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return trimmed;
|
|
24
|
+
}
|
|
25
|
+
function isValidEventName(value) {
|
|
26
|
+
return normalizeEventName(value) !== null;
|
|
27
|
+
}
|
|
28
|
+
exports.EVENTRA_SDK_SHIM = `declare module "@eventra_dev/eventra-sdk" {
|
|
29
|
+
export interface TrackOptions {
|
|
30
|
+
userId?: string;
|
|
31
|
+
properties?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
export interface TrackerOptions {
|
|
34
|
+
apiKey: string;
|
|
35
|
+
endpoint?: string;
|
|
36
|
+
}
|
|
37
|
+
export class Eventra {
|
|
38
|
+
constructor(options: TrackerOptions);
|
|
39
|
+
track(name: string, options?: TrackOptions): void;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
`;
|