@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.
@@ -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.4",
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/eventa-cli"
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 && chmod +x dist/index.js",
17
+ "build": "tsc",
18
18
  "dev": "tsx src/index.ts"
19
19
  },
20
20
  "dependencies": {
@@ -39,6 +39,7 @@ export async function init() {
39
39
  apiKey: answers.apiKey || "",
40
40
  events: [],
41
41
  wrappers: [],
42
+ functionWrappers: [],
42
43
  sync: {
43
44
  include: ["**/*.{ts,tsx,js,jsx}"],
44
45
  exclude: [
@@ -5,12 +5,15 @@ import {
5
5
  saveConfig
6
6
  } from "../utils/config";
7
7
 
8
- const EVENTRA_ENDPOINT = process.env.EVENTRA_ENDPOINT ?? "";
8
+ import pkg from "../../package.json";
9
9
 
10
- const CLI_VERSION = "0.0.1";
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
- let config = await loadConfig();
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
- if (!config.events.length) {
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("Sending events...")
80
+ chalk.blue(
81
+ `Sending ${config.events.length} events...`
82
+ )
61
83
  );
62
84
 
63
85
  try {
64
- const res = await fetch(EVENTRA_ENDPOINT,
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.status >= 400) {
107
+ if (!res.ok) {
85
108
  console.log(
86
109
  chalk.red(
87
- `Failed (${res.status})`
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 = await res.json();
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
- } catch {
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.red("Network error")
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
  }