@eventra_dev/eventra-cli 0.0.7 → 0.0.8
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/dist/commands/sync.js +42 -10
- package/dist/utils/extract.js +61 -37
- package/dist/utils/scanners/component-wrappers.js +15 -14
- package/dist/utils/scanners/function-wrappers.js +20 -20
- package/package.json +1 -1
- package/src/commands/sync.ts +74 -30
- package/src/types.ts +6 -0
- package/src/utils/extract.ts +76 -53
- package/src/utils/scanners/component-wrappers.ts +23 -33
- package/src/utils/scanners/function-wrappers.ts +40 -33
package/dist/commands/sync.js
CHANGED
|
@@ -8,6 +8,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
8
8
|
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
9
9
|
const ts_morph_1 = require("ts-morph");
|
|
10
10
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
11
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
11
12
|
const config_1 = require("../utils/config");
|
|
12
13
|
const router_1 = require("../utils/parsers/router");
|
|
13
14
|
const vue_1 = require("../utils/parsers/vue");
|
|
@@ -25,16 +26,10 @@ async function sync() {
|
|
|
25
26
|
console.log(chalk_1.default.blue("Scanning project..."));
|
|
26
27
|
const project = new ts_morph_1.Project();
|
|
27
28
|
const events = new Set();
|
|
29
|
+
const aliases = config.aliases ?? {};
|
|
28
30
|
const files = await (0, fast_glob_1.default)(config.sync.include, {
|
|
29
31
|
ignore: config.sync.exclude
|
|
30
32
|
});
|
|
31
|
-
const functionWrappers = (config.functionWrappers ?? []).map((w) => ({
|
|
32
|
-
name: w.name,
|
|
33
|
-
path: w.event
|
|
34
|
-
? `0.${w.event}`
|
|
35
|
-
: "0"
|
|
36
|
-
}));
|
|
37
|
-
const componentWrappers = config.wrappers ?? [];
|
|
38
33
|
for (const file of files) {
|
|
39
34
|
const parser = (0, router_1.detectParser)(file);
|
|
40
35
|
let content = await promises_1.default.readFile(file, "utf-8");
|
|
@@ -48,10 +43,47 @@ async function sync() {
|
|
|
48
43
|
? file
|
|
49
44
|
: file + ".tsx";
|
|
50
45
|
const source = project.createSourceFile(virtualFile, content, { overwrite: true });
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
const found = [
|
|
47
|
+
...(0, track_1.scanTrack)(source),
|
|
48
|
+
...(0, function_wrappers_1.scanFunctionWrappers)(source, config.functionWrappers ?? []),
|
|
49
|
+
...(0, component_wrappers_1.scanComponentWrappers)(source, config.wrappers ?? [])
|
|
50
|
+
];
|
|
51
|
+
for (const event of found) {
|
|
52
|
+
if (!event)
|
|
53
|
+
continue;
|
|
54
|
+
const value = typeof event === "string"
|
|
55
|
+
? event
|
|
56
|
+
: event.value;
|
|
57
|
+
const dynamic = typeof event === "string"
|
|
58
|
+
? false
|
|
59
|
+
: event.dynamic;
|
|
60
|
+
// alias exists
|
|
61
|
+
if (aliases[value]) {
|
|
62
|
+
events.add(aliases[value]);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// dynamic event
|
|
66
|
+
if (dynamic) {
|
|
67
|
+
console.log(chalk_1.default.yellow("\nDynamic event detected:"));
|
|
68
|
+
console.log(chalk_1.default.gray(value));
|
|
69
|
+
const { name } = await inquirer_1.default.prompt([
|
|
70
|
+
{
|
|
71
|
+
type: "input",
|
|
72
|
+
name: "name",
|
|
73
|
+
message: "Enter event name:",
|
|
74
|
+
validate: (v) => v
|
|
75
|
+
? true
|
|
76
|
+
: "Required"
|
|
77
|
+
}
|
|
78
|
+
]);
|
|
79
|
+
aliases[value] = name;
|
|
80
|
+
events.add(name);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
events.add(value);
|
|
84
|
+
}
|
|
54
85
|
}
|
|
86
|
+
config.aliases = aliases;
|
|
55
87
|
const list = [...events].sort();
|
|
56
88
|
config.events = list;
|
|
57
89
|
await (0, config_1.saveConfig)(config);
|
package/dist/utils/extract.js
CHANGED
|
@@ -1,44 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.extractExpression = extractExpression;
|
|
4
4
|
const ts_morph_1 = require("ts-morph");
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const obj = node;
|
|
16
|
-
const prop = obj.getProperty(parts[i]);
|
|
17
|
-
if (!prop)
|
|
18
|
-
return null;
|
|
19
|
-
if (!ts_morph_1.Node.isPropertyAssignment(prop)) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const initializer = prop.getInitializer();
|
|
23
|
-
if (!initializer)
|
|
24
|
-
return null;
|
|
25
|
-
node = unwrap(initializer);
|
|
26
|
-
}
|
|
27
|
-
if (ts_morph_1.Node.isStringLiteral(node)) {
|
|
28
|
-
return node.getLiteralText();
|
|
29
|
-
}
|
|
30
|
-
if (node.getKind() ===
|
|
5
|
+
function extractExpression(expr) {
|
|
6
|
+
// "signup"
|
|
7
|
+
if (ts_morph_1.Node.isStringLiteral(expr)) {
|
|
8
|
+
return {
|
|
9
|
+
value: expr.getLiteralText(),
|
|
10
|
+
dynamic: false
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
// `signup`
|
|
14
|
+
if (expr.getKind() ===
|
|
31
15
|
ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
return {
|
|
17
|
+
value: expr
|
|
18
|
+
.getText()
|
|
19
|
+
.replace(/`/g, ""),
|
|
20
|
+
dynamic: false
|
|
21
|
+
};
|
|
35
22
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
23
|
+
// template `${event}`
|
|
24
|
+
if (ts_morph_1.Node.isTemplateExpression(expr)) {
|
|
25
|
+
return {
|
|
26
|
+
value: expr.getText(),
|
|
27
|
+
dynamic: true
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// ROUTES.APP
|
|
31
|
+
if (ts_morph_1.Node.isPropertyAccessExpression(expr)) {
|
|
32
|
+
return {
|
|
33
|
+
value: expr.getText(),
|
|
34
|
+
dynamic: true
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// EVENT
|
|
38
|
+
if (ts_morph_1.Node.isIdentifier(expr)) {
|
|
39
|
+
return {
|
|
40
|
+
value: expr.getText(),
|
|
41
|
+
dynamic: true
|
|
42
|
+
};
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
// getEvent()
|
|
45
|
+
if (ts_morph_1.Node.isCallExpression(expr)) {
|
|
46
|
+
return {
|
|
47
|
+
value: expr
|
|
48
|
+
.getExpression()
|
|
49
|
+
.getText(),
|
|
50
|
+
dynamic: true
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// condition ? "a" : "b"
|
|
54
|
+
if (ts_morph_1.Node.isConditionalExpression(expr)) {
|
|
55
|
+
return {
|
|
56
|
+
value: expr.getText(),
|
|
57
|
+
dynamic: true
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// array[index]
|
|
61
|
+
if (ts_morph_1.Node.isElementAccessExpression(expr)) {
|
|
62
|
+
return {
|
|
63
|
+
value: expr.getText(),
|
|
64
|
+
dynamic: true
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
44
68
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.scanComponentWrappers = scanComponentWrappers;
|
|
4
4
|
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
const extract_1 = require("../extract");
|
|
5
6
|
function scanComponentWrappers(source, wrappers) {
|
|
6
7
|
const events = new Set();
|
|
7
8
|
const elements = [
|
|
@@ -32,21 +33,21 @@ function scanComponentWrappers(source, wrappers) {
|
|
|
32
33
|
const init = attrNode.getInitializer();
|
|
33
34
|
if (!init)
|
|
34
35
|
continue;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
// event="signup"
|
|
37
|
+
if (ts_morph_1.Node.isStringLiteral(init)) {
|
|
38
|
+
events.add({
|
|
39
|
+
value: init.getLiteralText(),
|
|
40
|
+
dynamic: false
|
|
41
|
+
});
|
|
39
42
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const expr = init
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
events.add(value.getLiteralText());
|
|
49
|
-
}
|
|
43
|
+
// event={...}
|
|
44
|
+
if (ts_morph_1.Node.isJsxExpression(init)) {
|
|
45
|
+
const expr = init.getExpression();
|
|
46
|
+
if (!expr)
|
|
47
|
+
continue;
|
|
48
|
+
const result = (0, extract_1.extractExpression)(expr);
|
|
49
|
+
if (result)
|
|
50
|
+
events.add(result);
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
}
|
|
@@ -13,20 +13,18 @@ function scanFunctionWrappers(source, wrappers) {
|
|
|
13
13
|
for (const wrapper of wrappers) {
|
|
14
14
|
if (wrapper.name !== name)
|
|
15
15
|
continue;
|
|
16
|
-
const
|
|
17
|
-
if (
|
|
18
|
-
events.add(
|
|
16
|
+
const result = extractEventFromArgs(call, wrapper.event);
|
|
17
|
+
if (result)
|
|
18
|
+
events.add(result);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
return events;
|
|
22
22
|
}
|
|
23
23
|
function getFunctionName(call) {
|
|
24
24
|
const expression = call.getExpression();
|
|
25
|
-
// trackFeature()
|
|
26
25
|
if (ts_morph_1.Node.isIdentifier(expression)) {
|
|
27
26
|
return expression.getText();
|
|
28
27
|
}
|
|
29
|
-
// analytics.trackFeature()
|
|
30
28
|
if (ts_morph_1.Node.isPropertyAccessExpression(expression)) {
|
|
31
29
|
return getDeepName(expression);
|
|
32
30
|
}
|
|
@@ -47,25 +45,27 @@ function extractEventFromArgs(call, event) {
|
|
|
47
45
|
const args = call.getArguments();
|
|
48
46
|
for (let i = 0; i < args.length; i++) {
|
|
49
47
|
const arg = args[i];
|
|
50
|
-
//
|
|
48
|
+
// track("event")
|
|
51
49
|
if (!event) {
|
|
52
|
-
|
|
53
|
-
return arg.getLiteralText();
|
|
54
|
-
}
|
|
55
|
-
// template literal
|
|
56
|
-
if (arg.getKind() ===
|
|
57
|
-
ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
58
|
-
return arg
|
|
59
|
-
.getText()
|
|
60
|
-
.replace(/`/g, "");
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// object case
|
|
64
|
-
if (event) {
|
|
65
|
-
const result = (0, extract_1.extractEvent)(call, `${i}.${event}`);
|
|
50
|
+
const result = (0, extract_1.extractExpression)(arg);
|
|
66
51
|
if (result)
|
|
67
52
|
return result;
|
|
68
53
|
}
|
|
54
|
+
// track({ event: "..." })
|
|
55
|
+
if (event) {
|
|
56
|
+
const obj = arg.asKind(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
|
|
57
|
+
if (!obj)
|
|
58
|
+
continue;
|
|
59
|
+
const prop = obj.getProperty(event);
|
|
60
|
+
if (!prop)
|
|
61
|
+
continue;
|
|
62
|
+
if (ts_morph_1.Node.isPropertyAssignment(prop)) {
|
|
63
|
+
const init = prop.getInitializer();
|
|
64
|
+
if (!init)
|
|
65
|
+
continue;
|
|
66
|
+
return (0, extract_1.extractExpression)(init);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
69
|
}
|
|
70
70
|
return null;
|
|
71
71
|
}
|
package/package.json
CHANGED
package/src/commands/sync.ts
CHANGED
|
@@ -2,6 +2,7 @@ import chalk from "chalk";
|
|
|
2
2
|
import fg from "fast-glob";
|
|
3
3
|
import { Project } from "ts-morph";
|
|
4
4
|
import fs from "fs/promises";
|
|
5
|
+
import inquirer from "inquirer";
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
8
|
loadConfig,
|
|
@@ -34,6 +35,9 @@ export async function sync() {
|
|
|
34
35
|
const project = new Project();
|
|
35
36
|
const events = new Set<string>();
|
|
36
37
|
|
|
38
|
+
const aliases =
|
|
39
|
+
config.aliases ?? {};
|
|
40
|
+
|
|
37
41
|
const files = await fg(
|
|
38
42
|
config.sync.include,
|
|
39
43
|
{
|
|
@@ -41,18 +45,6 @@ export async function sync() {
|
|
|
41
45
|
}
|
|
42
46
|
);
|
|
43
47
|
|
|
44
|
-
const functionWrappers =
|
|
45
|
-
(config.functionWrappers ?? []).map(
|
|
46
|
-
(w) => ({
|
|
47
|
-
name: w.name,
|
|
48
|
-
path: w.event
|
|
49
|
-
? `0.${w.event}`
|
|
50
|
-
: "0"
|
|
51
|
-
})
|
|
52
|
-
);
|
|
53
|
-
const componentWrappers =
|
|
54
|
-
config.wrappers ?? [];
|
|
55
|
-
|
|
56
48
|
for (const file of files) {
|
|
57
49
|
const parser =
|
|
58
50
|
detectParser(file);
|
|
@@ -84,26 +76,78 @@ export async function sync() {
|
|
|
84
76
|
{ overwrite: true }
|
|
85
77
|
);
|
|
86
78
|
|
|
87
|
-
|
|
88
|
-
(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
79
|
+
const found = [
|
|
80
|
+
...scanTrack(source),
|
|
81
|
+
...scanFunctionWrappers(
|
|
82
|
+
source,
|
|
83
|
+
config.functionWrappers ?? []
|
|
84
|
+
),
|
|
85
|
+
...scanComponentWrappers(
|
|
86
|
+
source,
|
|
87
|
+
config.wrappers ?? []
|
|
88
|
+
)
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
for (const event of found) {
|
|
92
|
+
if (!event) continue;
|
|
93
|
+
|
|
94
|
+
const value =
|
|
95
|
+
typeof event === "string"
|
|
96
|
+
? event
|
|
97
|
+
: event.value;
|
|
98
|
+
|
|
99
|
+
const dynamic =
|
|
100
|
+
typeof event === "string"
|
|
101
|
+
? false
|
|
102
|
+
: event.dynamic;
|
|
103
|
+
|
|
104
|
+
// alias exists
|
|
105
|
+
if (aliases[value]) {
|
|
106
|
+
events.add(
|
|
107
|
+
aliases[value]
|
|
108
|
+
);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// dynamic event
|
|
113
|
+
if (dynamic) {
|
|
114
|
+
console.log(
|
|
115
|
+
chalk.yellow(
|
|
116
|
+
"\nDynamic event detected:"
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
console.log(
|
|
121
|
+
chalk.gray(value)
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const { name } =
|
|
125
|
+
await inquirer.prompt([
|
|
126
|
+
{
|
|
127
|
+
type: "input",
|
|
128
|
+
name: "name",
|
|
129
|
+
message:
|
|
130
|
+
"Enter event name:",
|
|
131
|
+
validate: (v) =>
|
|
132
|
+
v
|
|
133
|
+
? true
|
|
134
|
+
: "Required"
|
|
135
|
+
}
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
aliases[value] = name;
|
|
139
|
+
|
|
140
|
+
events.add(name);
|
|
141
|
+
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
events.add(value);
|
|
146
|
+
}
|
|
105
147
|
}
|
|
106
148
|
|
|
149
|
+
config.aliases = aliases;
|
|
150
|
+
|
|
107
151
|
const list =
|
|
108
152
|
[...events].sort();
|
|
109
153
|
|
package/src/types.ts
CHANGED
|
@@ -13,8 +13,14 @@ export type EventraConfig = {
|
|
|
13
13
|
events: string[];
|
|
14
14
|
wrappers: ComponentWrapper[];
|
|
15
15
|
functionWrappers: FunctionWrapper[];
|
|
16
|
+
aliases?: Record<string, string>;
|
|
16
17
|
sync: {
|
|
17
18
|
include: string[];
|
|
18
19
|
exclude: string[];
|
|
19
20
|
};
|
|
20
21
|
};
|
|
22
|
+
|
|
23
|
+
export type ExtractedEvent = {
|
|
24
|
+
value: string;
|
|
25
|
+
dynamic: boolean;
|
|
26
|
+
};
|
package/src/utils/extract.ts
CHANGED
|
@@ -1,74 +1,97 @@
|
|
|
1
1
|
import {
|
|
2
|
-
CallExpression,
|
|
3
2
|
Node,
|
|
4
|
-
|
|
5
|
-
SyntaxKind,
|
|
3
|
+
SyntaxKind
|
|
6
4
|
} from "ts-morph";
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
call: CallExpression,
|
|
10
|
-
path: string
|
|
11
|
-
): string | null {
|
|
12
|
-
const parts = path.split(".");
|
|
6
|
+
import { ExtractedEvent } from "../types";
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
export function extractExpression(
|
|
9
|
+
expr: Node
|
|
10
|
+
): ExtractedEvent | null {
|
|
16
11
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const obj: ObjectLiteralExpression =
|
|
27
|
-
node;
|
|
28
|
-
|
|
29
|
-
const prop =
|
|
30
|
-
obj.getProperty(parts[i]);
|
|
31
|
-
|
|
32
|
-
if (!prop) return null;
|
|
33
|
-
|
|
34
|
-
if (!Node.isPropertyAssignment(prop)) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const initializer =
|
|
39
|
-
prop.getInitializer();
|
|
12
|
+
// "signup"
|
|
13
|
+
if (Node.isStringLiteral(expr)) {
|
|
14
|
+
return {
|
|
15
|
+
value: expr.getLiteralText(),
|
|
16
|
+
dynamic: false
|
|
17
|
+
};
|
|
18
|
+
}
|
|
40
19
|
|
|
41
|
-
|
|
20
|
+
// `signup`
|
|
21
|
+
if (
|
|
22
|
+
expr.getKind() ===
|
|
23
|
+
SyntaxKind.NoSubstitutionTemplateLiteral
|
|
24
|
+
) {
|
|
25
|
+
return {
|
|
26
|
+
value: expr
|
|
27
|
+
.getText()
|
|
28
|
+
.replace(/`/g, ""),
|
|
29
|
+
dynamic: false
|
|
30
|
+
};
|
|
31
|
+
}
|
|
42
32
|
|
|
43
|
-
|
|
33
|
+
// template `${event}`
|
|
34
|
+
if (
|
|
35
|
+
Node.isTemplateExpression(expr)
|
|
36
|
+
) {
|
|
37
|
+
return {
|
|
38
|
+
value: expr.getText(),
|
|
39
|
+
dynamic: true
|
|
40
|
+
};
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
// ROUTES.APP
|
|
44
|
+
if (
|
|
45
|
+
Node.isPropertyAccessExpression(expr)
|
|
46
|
+
) {
|
|
47
|
+
return {
|
|
48
|
+
value: expr.getText(),
|
|
49
|
+
dynamic: true
|
|
50
|
+
};
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
// EVENT
|
|
50
54
|
if (
|
|
51
|
-
|
|
52
|
-
SyntaxKind.NoSubstitutionTemplateLiteral
|
|
55
|
+
Node.isIdentifier(expr)
|
|
53
56
|
) {
|
|
54
|
-
return
|
|
55
|
-
.getText()
|
|
56
|
-
|
|
57
|
+
return {
|
|
58
|
+
value: expr.getText(),
|
|
59
|
+
dynamic: true
|
|
60
|
+
};
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
// getEvent()
|
|
64
|
+
if (
|
|
65
|
+
Node.isCallExpression(expr)
|
|
66
|
+
) {
|
|
67
|
+
return {
|
|
68
|
+
value:
|
|
69
|
+
expr
|
|
70
|
+
.getExpression()
|
|
71
|
+
.getText(),
|
|
72
|
+
dynamic: true
|
|
73
|
+
};
|
|
74
|
+
}
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
76
|
+
// condition ? "a" : "b"
|
|
77
|
+
if (
|
|
78
|
+
Node.isConditionalExpression(expr)
|
|
79
|
+
) {
|
|
80
|
+
return {
|
|
81
|
+
value: expr.getText(),
|
|
82
|
+
dynamic: true
|
|
83
|
+
};
|
|
84
|
+
}
|
|
64
85
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
86
|
+
// array[index]
|
|
87
|
+
if (
|
|
88
|
+
Node.isElementAccessExpression(expr)
|
|
89
|
+
) {
|
|
90
|
+
return {
|
|
91
|
+
value: expr.getText(),
|
|
92
|
+
dynamic: true
|
|
93
|
+
};
|
|
71
94
|
}
|
|
72
95
|
|
|
73
|
-
return
|
|
96
|
+
return null;
|
|
74
97
|
}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SourceFile,
|
|
3
3
|
SyntaxKind,
|
|
4
|
+
Node
|
|
4
5
|
} from "ts-morph";
|
|
5
6
|
|
|
6
|
-
import { ComponentWrapper } from "../../types";
|
|
7
|
+
import { ComponentWrapper, ExtractedEvent } from "../../types";
|
|
8
|
+
import { extractExpression } from "../extract";
|
|
7
9
|
|
|
8
10
|
export function scanComponentWrappers(
|
|
9
11
|
source: SourceFile,
|
|
10
12
|
wrappers: ComponentWrapper[]
|
|
11
13
|
) {
|
|
12
|
-
const events =
|
|
14
|
+
const events =
|
|
15
|
+
new Set<ExtractedEvent>();
|
|
13
16
|
|
|
14
17
|
const elements = [
|
|
15
18
|
...source.getDescendantsOfKind(
|
|
@@ -61,44 +64,31 @@ export function scanComponentWrappers(
|
|
|
61
64
|
|
|
62
65
|
if (!init) continue;
|
|
63
66
|
|
|
67
|
+
// event="signup"
|
|
64
68
|
if (
|
|
65
|
-
|
|
66
|
-
SyntaxKind.StringLiteral
|
|
69
|
+
Node.isStringLiteral(init)
|
|
67
70
|
) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
events.add(
|
|
74
|
-
value.getLiteralText()
|
|
75
|
-
);
|
|
71
|
+
events.add({
|
|
72
|
+
value:
|
|
73
|
+
init.getLiteralText(),
|
|
74
|
+
dynamic: false
|
|
75
|
+
});
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// event={...}
|
|
78
79
|
if (
|
|
79
|
-
|
|
80
|
-
SyntaxKind.JsxExpression
|
|
80
|
+
Node.isJsxExpression(init)
|
|
81
81
|
) {
|
|
82
82
|
const expr =
|
|
83
|
-
init
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
) {
|
|
93
|
-
const value =
|
|
94
|
-
expr.asKindOrThrow(
|
|
95
|
-
SyntaxKind.StringLiteral
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
events.add(
|
|
99
|
-
value.getLiteralText()
|
|
100
|
-
);
|
|
101
|
-
}
|
|
83
|
+
init.getExpression();
|
|
84
|
+
|
|
85
|
+
if (!expr) continue;
|
|
86
|
+
|
|
87
|
+
const result =
|
|
88
|
+
extractExpression(expr);
|
|
89
|
+
|
|
90
|
+
if (result)
|
|
91
|
+
events.add(result);
|
|
102
92
|
}
|
|
103
93
|
}
|
|
104
94
|
}
|
|
@@ -6,14 +6,15 @@ import {
|
|
|
6
6
|
PropertyAccessExpression,
|
|
7
7
|
} from "ts-morph";
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
import { FunctionWrapper } from "../../types";
|
|
9
|
+
import { extractExpression } from "../extract";
|
|
10
|
+
import { FunctionWrapper, ExtractedEvent } from "../../types";
|
|
11
11
|
|
|
12
12
|
export function scanFunctionWrappers(
|
|
13
13
|
source: SourceFile,
|
|
14
14
|
wrappers: FunctionWrapper[]
|
|
15
15
|
) {
|
|
16
|
-
const events =
|
|
16
|
+
const events =
|
|
17
|
+
new Set<ExtractedEvent>();
|
|
17
18
|
|
|
18
19
|
const calls =
|
|
19
20
|
source.getDescendantsOfKind(
|
|
@@ -30,14 +31,14 @@ export function scanFunctionWrappers(
|
|
|
30
31
|
if (wrapper.name !== name)
|
|
31
32
|
continue;
|
|
32
33
|
|
|
33
|
-
const
|
|
34
|
+
const result =
|
|
34
35
|
extractEventFromArgs(
|
|
35
36
|
call,
|
|
36
37
|
wrapper.event
|
|
37
38
|
);
|
|
38
39
|
|
|
39
|
-
if (
|
|
40
|
-
events.add(
|
|
40
|
+
if (result)
|
|
41
|
+
events.add(result);
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -50,16 +51,12 @@ function getFunctionName(
|
|
|
50
51
|
const expression =
|
|
51
52
|
call.getExpression();
|
|
52
53
|
|
|
53
|
-
// trackFeature()
|
|
54
54
|
if (
|
|
55
|
-
Node.isIdentifier(
|
|
56
|
-
expression
|
|
57
|
-
)
|
|
55
|
+
Node.isIdentifier(expression)
|
|
58
56
|
) {
|
|
59
57
|
return expression.getText();
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
// analytics.trackFeature()
|
|
63
60
|
if (
|
|
64
61
|
Node.isPropertyAccessExpression(
|
|
65
62
|
expression
|
|
@@ -97,42 +94,52 @@ function getDeepName(
|
|
|
97
94
|
return name;
|
|
98
95
|
}
|
|
99
96
|
|
|
100
|
-
|
|
101
97
|
function extractEventFromArgs(
|
|
102
98
|
call: CallExpression,
|
|
103
99
|
event?: string
|
|
104
|
-
):
|
|
105
|
-
|
|
100
|
+
): ExtractedEvent | null {
|
|
101
|
+
|
|
102
|
+
const args =
|
|
103
|
+
call.getArguments();
|
|
106
104
|
|
|
107
105
|
for (let i = 0; i < args.length; i++) {
|
|
108
106
|
const arg = args[i];
|
|
109
107
|
|
|
110
|
-
//
|
|
108
|
+
// track("event")
|
|
111
109
|
if (!event) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
110
|
+
const result =
|
|
111
|
+
extractExpression(arg);
|
|
115
112
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
arg.getKind() ===
|
|
119
|
-
SyntaxKind.NoSubstitutionTemplateLiteral
|
|
120
|
-
) {
|
|
121
|
-
return arg
|
|
122
|
-
.getText()
|
|
123
|
-
.replace(/`/g, "");
|
|
124
|
-
}
|
|
113
|
+
if (result)
|
|
114
|
+
return result;
|
|
125
115
|
}
|
|
126
116
|
|
|
127
|
-
//
|
|
117
|
+
// track({ event: "..." })
|
|
128
118
|
if (event) {
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
`${i}.${event}`
|
|
119
|
+
const obj =
|
|
120
|
+
arg.asKind(
|
|
121
|
+
SyntaxKind.ObjectLiteralExpression
|
|
133
122
|
);
|
|
134
123
|
|
|
135
|
-
if (
|
|
124
|
+
if (!obj) continue;
|
|
125
|
+
|
|
126
|
+
const prop =
|
|
127
|
+
obj.getProperty(event);
|
|
128
|
+
|
|
129
|
+
if (!prop) continue;
|
|
130
|
+
|
|
131
|
+
if (
|
|
132
|
+
Node.isPropertyAssignment(prop)
|
|
133
|
+
) {
|
|
134
|
+
const init =
|
|
135
|
+
prop.getInitializer();
|
|
136
|
+
|
|
137
|
+
if (!init) continue;
|
|
138
|
+
|
|
139
|
+
return extractExpression(
|
|
140
|
+
init
|
|
141
|
+
);
|
|
142
|
+
}
|
|
136
143
|
}
|
|
137
144
|
}
|
|
138
145
|
|