@eventra_dev/eventra-cli 0.0.4 → 0.0.5
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 +123 -44
- package/dist/commands/init.js +1 -0
- package/dist/commands/send.js +41 -7
- package/dist/commands/sync.js +27 -194
- package/dist/index.js +0 -0
- package/dist/types.js +2 -0
- package/dist/utils/config.js +4 -1
- package/dist/utils/extract.js +29 -0
- package/dist/utils/parsers/astro.js +6 -0
- package/dist/utils/parsers/router.js +12 -0
- package/dist/utils/parsers/svelte.js +6 -0
- package/dist/utils/parsers/vue.js +10 -0
- package/dist/utils/scanners/component-wrappers.js +57 -0
- package/dist/utils/scanners/function-wrappers.js +35 -0
- package/dist/utils/scanners/track.js +42 -0
- package/package.json +3 -3
- package/src/commands/init.ts +1 -0
- package/src/commands/send.ts +101 -17
- package/src/commands/sync.ts +51 -347
- package/src/types.ts +20 -0
- package/src/utils/config.ts +24 -7
- package/src/utils/extract.ts +51 -0
- package/src/utils/parsers/astro.ts +5 -0
- package/src/utils/parsers/router.ts +14 -0
- package/src/utils/parsers/svelte.ts +5 -0
- package/src/utils/parsers/vue.ts +19 -0
- package/src/utils/scanners/component-wrappers.ts +110 -0
- package/src/utils/scanners/function-wrappers.ts +67 -0
- package/src/utils/scanners/track.ts +84 -0
- package/tsconfig.json +2 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanComponentWrappers = scanComponentWrappers;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
function scanComponentWrappers(source, wrappers) {
|
|
6
|
+
const events = new Set();
|
|
7
|
+
const elements = [
|
|
8
|
+
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxOpeningElement),
|
|
9
|
+
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxSelfClosingElement)
|
|
10
|
+
];
|
|
11
|
+
for (const el of elements) {
|
|
12
|
+
const name = el
|
|
13
|
+
.getTagNameNode()
|
|
14
|
+
.getText()
|
|
15
|
+
.toLowerCase();
|
|
16
|
+
for (const wrapper of wrappers) {
|
|
17
|
+
if (name !==
|
|
18
|
+
wrapper.name.toLowerCase())
|
|
19
|
+
continue;
|
|
20
|
+
const attrs = el.getAttributes();
|
|
21
|
+
for (const attr of attrs) {
|
|
22
|
+
const attrNode = attr.asKind(ts_morph_1.SyntaxKind.JsxAttribute);
|
|
23
|
+
if (!attrNode)
|
|
24
|
+
continue;
|
|
25
|
+
const key = attrNode
|
|
26
|
+
.getNameNode()
|
|
27
|
+
.getText()
|
|
28
|
+
.toLowerCase();
|
|
29
|
+
if (key !==
|
|
30
|
+
wrapper.prop.toLowerCase())
|
|
31
|
+
continue;
|
|
32
|
+
const init = attrNode.getInitializer();
|
|
33
|
+
if (!init)
|
|
34
|
+
continue;
|
|
35
|
+
// event="signup"
|
|
36
|
+
if (init.getKind() ===
|
|
37
|
+
ts_morph_1.SyntaxKind.StringLiteral) {
|
|
38
|
+
const value = init.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral);
|
|
39
|
+
events.add(value.getLiteralText());
|
|
40
|
+
}
|
|
41
|
+
// event={"signup"}
|
|
42
|
+
if (init.getKind() ===
|
|
43
|
+
ts_morph_1.SyntaxKind.JsxExpression) {
|
|
44
|
+
const expr = init
|
|
45
|
+
.asKindOrThrow(ts_morph_1.SyntaxKind.JsxExpression)
|
|
46
|
+
.getExpression();
|
|
47
|
+
if (expr?.getKind() ===
|
|
48
|
+
ts_morph_1.SyntaxKind.StringLiteral) {
|
|
49
|
+
const value = expr.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral);
|
|
50
|
+
events.add(value.getLiteralText());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return events;
|
|
57
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanFunctionWrappers = scanFunctionWrappers;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
const extract_1 = require("../extract");
|
|
6
|
+
function scanFunctionWrappers(source, wrappers) {
|
|
7
|
+
const events = new Set();
|
|
8
|
+
const calls = source.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
|
|
9
|
+
for (const call of calls) {
|
|
10
|
+
const expression = call.getExpression();
|
|
11
|
+
let name = null;
|
|
12
|
+
// trackFeature()
|
|
13
|
+
if (expression.getKind() ===
|
|
14
|
+
ts_morph_1.SyntaxKind.Identifier) {
|
|
15
|
+
name =
|
|
16
|
+
expression.getText();
|
|
17
|
+
}
|
|
18
|
+
// analytics.trackFeature()
|
|
19
|
+
if (expression.getKind() ===
|
|
20
|
+
ts_morph_1.SyntaxKind.PropertyAccessExpression) {
|
|
21
|
+
const prop = expression.asKindOrThrow(ts_morph_1.SyntaxKind.PropertyAccessExpression);
|
|
22
|
+
name = prop.getName();
|
|
23
|
+
}
|
|
24
|
+
if (!name)
|
|
25
|
+
continue;
|
|
26
|
+
for (const wrapper of wrappers) {
|
|
27
|
+
if (name !== wrapper.name)
|
|
28
|
+
continue;
|
|
29
|
+
const event = (0, extract_1.extractEvent)(call, wrapper.path);
|
|
30
|
+
if (event)
|
|
31
|
+
events.add(event);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return events;
|
|
35
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanTrack = scanTrack;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
function scanTrack(source) {
|
|
6
|
+
const events = new Set();
|
|
7
|
+
const calls = source.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
|
|
8
|
+
for (const call of calls) {
|
|
9
|
+
const expr = call.getExpression();
|
|
10
|
+
let isTrack = false;
|
|
11
|
+
// track()
|
|
12
|
+
if (expr.getKind() ===
|
|
13
|
+
ts_morph_1.SyntaxKind.Identifier) {
|
|
14
|
+
isTrack =
|
|
15
|
+
expr.getText() === "track";
|
|
16
|
+
}
|
|
17
|
+
// analytics.track()
|
|
18
|
+
if (expr.getKind() ===
|
|
19
|
+
ts_morph_1.SyntaxKind.PropertyAccessExpression) {
|
|
20
|
+
const prop = expr.asKindOrThrow(ts_morph_1.SyntaxKind.PropertyAccessExpression);
|
|
21
|
+
isTrack =
|
|
22
|
+
prop.getName() === "track";
|
|
23
|
+
}
|
|
24
|
+
if (!isTrack)
|
|
25
|
+
continue;
|
|
26
|
+
const arg = call.getArguments()[0];
|
|
27
|
+
if (!arg)
|
|
28
|
+
continue;
|
|
29
|
+
if (arg.getKind() ===
|
|
30
|
+
ts_morph_1.SyntaxKind.StringLiteral) {
|
|
31
|
+
const value = arg.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral);
|
|
32
|
+
events.add(value.getLiteralText());
|
|
33
|
+
}
|
|
34
|
+
// template literal
|
|
35
|
+
if (arg.getKind() ===
|
|
36
|
+
ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
37
|
+
const value = arg.asKindOrThrow(ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral);
|
|
38
|
+
events.add(value.getLiteralText());
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return events;
|
|
42
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventra_dev/eventra-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Eventra CLI",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
"access": "public",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/and-1991/
|
|
12
|
+
"url": "https://github.com/and-1991/eventra-cli"
|
|
13
13
|
},
|
|
14
14
|
"homepage": "https://eventra.dev",
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "tsc
|
|
17
|
+
"build": "tsc",
|
|
18
18
|
"dev": "tsx src/index.ts"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
package/src/commands/init.ts
CHANGED
package/src/commands/send.ts
CHANGED
|
@@ -5,12 +5,15 @@ import {
|
|
|
5
5
|
saveConfig
|
|
6
6
|
} from "../utils/config";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import pkg from "../../package.json";
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const EVENTRA_ENDPOINT =
|
|
11
|
+
process.env.EVENTRA_ENDPOINT ?? "";
|
|
12
|
+
|
|
13
|
+
const CLI_VERSION = pkg.version;
|
|
11
14
|
|
|
12
15
|
export async function send() {
|
|
13
|
-
|
|
16
|
+
const config = await loadConfig();
|
|
14
17
|
|
|
15
18
|
if (!config) {
|
|
16
19
|
console.log(
|
|
@@ -23,6 +26,7 @@ export async function send() {
|
|
|
23
26
|
|
|
24
27
|
let apiKey = config.apiKey;
|
|
25
28
|
|
|
29
|
+
// ask api key
|
|
26
30
|
if (!apiKey) {
|
|
27
31
|
const answers =
|
|
28
32
|
await inquirer.prompt([
|
|
@@ -41,13 +45,12 @@ export async function send() {
|
|
|
41
45
|
await saveConfig(config);
|
|
42
46
|
|
|
43
47
|
console.log(
|
|
44
|
-
chalk.green(
|
|
45
|
-
"API key saved"
|
|
46
|
-
)
|
|
48
|
+
chalk.green("API key saved")
|
|
47
49
|
);
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
// no events
|
|
53
|
+
if (!config.events?.length) {
|
|
51
54
|
console.log(
|
|
52
55
|
chalk.yellow(
|
|
53
56
|
"No events found. Run 'eventra sync'"
|
|
@@ -56,12 +59,32 @@ export async function send() {
|
|
|
56
59
|
return;
|
|
57
60
|
}
|
|
58
61
|
|
|
62
|
+
if (!apiKey) {
|
|
63
|
+
console.log(
|
|
64
|
+
chalk.red("API key required")
|
|
65
|
+
);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!EVENTRA_ENDPOINT) {
|
|
70
|
+
console.log(
|
|
71
|
+
chalk.red(
|
|
72
|
+
"EVENTRA_ENDPOINT not configured"
|
|
73
|
+
)
|
|
74
|
+
);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log("");
|
|
59
79
|
console.log(
|
|
60
|
-
chalk.blue(
|
|
80
|
+
chalk.blue(
|
|
81
|
+
`Sending ${config.events.length} events...`
|
|
82
|
+
)
|
|
61
83
|
);
|
|
62
84
|
|
|
63
85
|
try {
|
|
64
|
-
const res = await fetch(
|
|
86
|
+
const res = await fetch(
|
|
87
|
+
EVENTRA_ENDPOINT,
|
|
65
88
|
{
|
|
66
89
|
method: "POST",
|
|
67
90
|
headers: {
|
|
@@ -81,17 +104,27 @@ export async function send() {
|
|
|
81
104
|
}
|
|
82
105
|
);
|
|
83
106
|
|
|
84
|
-
if (res.
|
|
107
|
+
if (!res.ok) {
|
|
85
108
|
console.log(
|
|
86
109
|
chalk.red(
|
|
87
|
-
`
|
|
110
|
+
`Request failed (${res.status})`
|
|
88
111
|
)
|
|
89
112
|
);
|
|
90
113
|
|
|
114
|
+
try {
|
|
115
|
+
const text =
|
|
116
|
+
await res.text();
|
|
117
|
+
|
|
118
|
+
console.log(
|
|
119
|
+
chalk.gray(text)
|
|
120
|
+
);
|
|
121
|
+
} catch {}
|
|
122
|
+
|
|
91
123
|
return;
|
|
92
124
|
}
|
|
93
125
|
|
|
94
|
-
const data =
|
|
126
|
+
const data =
|
|
127
|
+
await res.json();
|
|
95
128
|
|
|
96
129
|
console.log(
|
|
97
130
|
chalk.green(
|
|
@@ -99,11 +132,10 @@ export async function send() {
|
|
|
99
132
|
)
|
|
100
133
|
);
|
|
101
134
|
|
|
135
|
+
// created
|
|
102
136
|
if (data.created?.length) {
|
|
103
137
|
console.log(
|
|
104
|
-
chalk.green(
|
|
105
|
-
"\nNew events:"
|
|
106
|
-
)
|
|
138
|
+
chalk.green("\nNew events:")
|
|
107
139
|
);
|
|
108
140
|
|
|
109
141
|
data.created.forEach(
|
|
@@ -116,9 +148,61 @@ export async function send() {
|
|
|
116
148
|
);
|
|
117
149
|
}
|
|
118
150
|
|
|
119
|
-
|
|
151
|
+
// existing
|
|
152
|
+
if (data.existing?.length) {
|
|
153
|
+
console.log(
|
|
154
|
+
chalk.gray(
|
|
155
|
+
"\nExisting events:"
|
|
156
|
+
)
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
data.existing.forEach(
|
|
160
|
+
(e: string) =>
|
|
161
|
+
console.log(
|
|
162
|
+
chalk.gray(
|
|
163
|
+
`• ${e}`
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// processing notice
|
|
170
|
+
if (data.created?.length) {
|
|
171
|
+
console.log("");
|
|
172
|
+
console.log(
|
|
173
|
+
chalk.yellow(
|
|
174
|
+
"Events queued for processing (~2 min)"
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
console.log(
|
|
179
|
+
chalk.gray(
|
|
180
|
+
"They will appear in dashboard shortly"
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.log("");
|
|
186
|
+
|
|
120
187
|
console.log(
|
|
121
|
-
chalk.
|
|
188
|
+
chalk.gray(
|
|
189
|
+
`Sent ${config.events.length} events`
|
|
190
|
+
)
|
|
122
191
|
);
|
|
192
|
+
|
|
193
|
+
} catch (err) {
|
|
194
|
+
console.log(
|
|
195
|
+
chalk.red(
|
|
196
|
+
"Network error"
|
|
197
|
+
)
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
if (err instanceof Error) {
|
|
201
|
+
console.log(
|
|
202
|
+
chalk.gray(
|
|
203
|
+
err.message
|
|
204
|
+
)
|
|
205
|
+
);
|
|
206
|
+
}
|
|
123
207
|
}
|
|
124
208
|
}
|