@eventra_dev/eventra-cli 0.0.18 → 0.0.19
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 +74 -166
- package/dist/commands/check.js +80 -43
- package/dist/commands/sync.js +93 -53
- package/dist/commands/watch.js +97 -0
- package/dist/index.js +10 -6
- package/dist/utils/detect-aliases.js +39 -0
- package/dist/utils/detect-wrappers.js +84 -0
- package/dist/utils/extract.js +18 -98
- package/dist/utils/scanners/component-wrappers.js +23 -20
- package/dist/utils/scanners/function-wrappers.js +16 -18
- package/dist/utils/scanners/track.js +20 -8
- package/package.json +2 -1
- package/src/commands/check.ts +100 -75
- package/src/commands/sync.ts +170 -110
- package/src/commands/watch.ts +113 -0
- package/src/index.ts +11 -6
- package/src/types.ts +4 -0
- package/src/utils/detect-aliases.ts +46 -0
- package/src/utils/detect-wrappers.ts +119 -0
- package/src/utils/extract.ts +20 -133
- package/src/utils/scanners/component-wrappers.ts +27 -25
- package/src/utils/scanners/function-wrappers.ts +47 -90
- package/src/utils/scanners/track.ts +23 -8
package/dist/commands/sync.js
CHANGED
|
@@ -10,6 +10,8 @@ const ts_morph_1 = require("ts-morph");
|
|
|
10
10
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
11
11
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
12
12
|
const config_1 = require("../utils/config");
|
|
13
|
+
const detect_wrappers_1 = require("../utils/detect-wrappers");
|
|
14
|
+
const detect_aliases_1 = require("../utils/detect-aliases");
|
|
13
15
|
const router_1 = require("../utils/parsers/router");
|
|
14
16
|
const vue_1 = require("../utils/parsers/vue");
|
|
15
17
|
const svelte_1 = require("../utils/parsers/svelte");
|
|
@@ -32,65 +34,103 @@ async function sync() {
|
|
|
32
34
|
ignore: config.sync.exclude
|
|
33
35
|
});
|
|
34
36
|
for (const file of files) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
? file
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const { value, dynamic } = event;
|
|
54
|
-
if (!value)
|
|
55
|
-
continue;
|
|
56
|
-
// alias
|
|
57
|
-
if (aliases[value]) {
|
|
58
|
-
console.log(chalk_1.default.gray(`alias: ${value} → ${aliases[value]}`));
|
|
59
|
-
events.add(aliases[value]);
|
|
60
|
-
continue;
|
|
37
|
+
try {
|
|
38
|
+
const parser = (0, router_1.detectParser)(file);
|
|
39
|
+
let content = await promises_1.default.readFile(file, "utf-8");
|
|
40
|
+
if (parser === "vue")
|
|
41
|
+
content = (0, vue_1.parseVue)(content);
|
|
42
|
+
if (parser === "svelte")
|
|
43
|
+
content = (0, svelte_1.parseSvelte)(content);
|
|
44
|
+
if (parser === "astro")
|
|
45
|
+
content = (0, astro_1.parseAstro)(content);
|
|
46
|
+
const virtualFile = parser === "ts" ? file : file + ".tsx";
|
|
47
|
+
const source = project.createSourceFile(virtualFile, content, { overwrite: true });
|
|
48
|
+
// AUTO ALIASES
|
|
49
|
+
const detectedAliases = (0, detect_aliases_1.detectAliases)(source);
|
|
50
|
+
for (const key in detectedAliases) {
|
|
51
|
+
if (!(key in aliases)) {
|
|
52
|
+
aliases[key] = detectedAliases[key];
|
|
53
|
+
console.log(chalk_1.default.green(`Detected alias: ${key} → ${detectedAliases[key]}`));
|
|
54
|
+
}
|
|
61
55
|
}
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
// AUTO WRAPPERS
|
|
57
|
+
const detected = (0, detect_wrappers_1.detectWrappers)(source);
|
|
58
|
+
// function wrappers
|
|
59
|
+
for (const fn of detected.functions) {
|
|
60
|
+
if (!config.functionWrappers?.some((w) => w.name === fn.name)) {
|
|
61
|
+
config.functionWrappers.push(fn);
|
|
62
|
+
console.log(chalk_1.default.green(`Detected function wrapper: ${fn.name}`));
|
|
63
|
+
}
|
|
66
64
|
}
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
// component wrappers
|
|
66
|
+
for (const comp of detected.components) {
|
|
67
|
+
if (!config.wrappers?.some((w) => w.name === comp.name)) {
|
|
68
|
+
config.wrappers.push(comp);
|
|
69
|
+
console.log(chalk_1.default.green(`Detected component wrapper: ${comp.name} (prop: ${comp.prop})`));
|
|
70
|
+
}
|
|
70
71
|
}
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
// SCAN EVENTS
|
|
73
|
+
const found = [
|
|
74
|
+
...(0, track_1.scanTrack)(source, config, aliases),
|
|
75
|
+
...(0, function_wrappers_1.scanFunctionWrappers)(source, config.functionWrappers ?? [], aliases),
|
|
76
|
+
...(0, component_wrappers_1.scanComponentWrappers)(source, config.wrappers ?? [], aliases)
|
|
77
|
+
];
|
|
78
|
+
for (const event of found) {
|
|
79
|
+
const { value, dynamic } = event;
|
|
80
|
+
if (!value)
|
|
81
|
+
continue;
|
|
82
|
+
// skip explicit ignore
|
|
83
|
+
if (value in aliases && aliases[value] === "__skip__") {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// resolve alias
|
|
87
|
+
if (value in aliases) {
|
|
88
|
+
events.add(aliases[value]);
|
|
89
|
+
continue;
|
|
79
90
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
// static
|
|
92
|
+
if (!dynamic) {
|
|
93
|
+
events.add(value);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// already handled
|
|
97
|
+
if (asked.has(value))
|
|
98
|
+
continue;
|
|
99
|
+
// ASK ONLY IF NEEDED
|
|
100
|
+
console.log(chalk_1.default.yellow("\nDynamic event detected:"));
|
|
101
|
+
console.log(chalk_1.default.gray(value));
|
|
102
|
+
const { name } = await inquirer_1.default.prompt([
|
|
103
|
+
{
|
|
104
|
+
type: "input",
|
|
105
|
+
name: "name",
|
|
106
|
+
message: "Enter event name (or type 'skip'):"
|
|
107
|
+
}
|
|
108
|
+
]);
|
|
109
|
+
const normalized = name?.trim();
|
|
110
|
+
asked.add(value);
|
|
111
|
+
if (!normalized || normalized === "skip") {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
// save alias
|
|
115
|
+
aliases[value] = normalized;
|
|
116
|
+
console.log(chalk_1.default.green(`Saved alias: ${value} → ${normalized}`));
|
|
117
|
+
events.add(normalized);
|
|
85
118
|
}
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
119
|
+
// free memory
|
|
120
|
+
project.removeSourceFile(source);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
console.log(chalk_1.default.gray(`Skipped file: ${file}`));
|
|
89
124
|
}
|
|
90
125
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
126
|
+
// SAVE CONFIG
|
|
127
|
+
config.aliases = Object.fromEntries(Object.entries(aliases).sort());
|
|
128
|
+
// MERGE
|
|
129
|
+
const merged = new Set([
|
|
130
|
+
...config.events,
|
|
131
|
+
...events
|
|
132
|
+
]);
|
|
133
|
+
config.events = [...merged].sort();
|
|
94
134
|
await (0, config_1.saveConfig)(config);
|
|
95
|
-
console.log(chalk_1.default.green(
|
|
135
|
+
console.log(chalk_1.default.green(`\nFound ${config.events.length} events`));
|
|
96
136
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.watch = watch;
|
|
7
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const ts_morph_1 = require("ts-morph");
|
|
10
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
11
|
+
const config_1 = require("../utils/config");
|
|
12
|
+
const router_1 = require("../utils/parsers/router");
|
|
13
|
+
const vue_1 = require("../utils/parsers/vue");
|
|
14
|
+
const svelte_1 = require("../utils/parsers/svelte");
|
|
15
|
+
const astro_1 = require("../utils/parsers/astro");
|
|
16
|
+
const track_1 = require("../utils/scanners/track");
|
|
17
|
+
const function_wrappers_1 = require("../utils/scanners/function-wrappers");
|
|
18
|
+
const component_wrappers_1 = require("../utils/scanners/component-wrappers");
|
|
19
|
+
async function watch() {
|
|
20
|
+
const config = await (0, config_1.loadConfig)();
|
|
21
|
+
if (!config) {
|
|
22
|
+
console.log(chalk_1.default.red("Run init first"));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(chalk_1.default.blue("Watching...\n"));
|
|
26
|
+
const project = new ts_morph_1.Project();
|
|
27
|
+
const aliases = config.aliases ?? {};
|
|
28
|
+
// уже известные события
|
|
29
|
+
const seen = new Set(config.events);
|
|
30
|
+
const queue = new Set();
|
|
31
|
+
let timer;
|
|
32
|
+
const processQueue = async () => {
|
|
33
|
+
const files = [...queue];
|
|
34
|
+
queue.clear();
|
|
35
|
+
for (const file of files) {
|
|
36
|
+
await handle(file);
|
|
37
|
+
}
|
|
38
|
+
config.events = [...new Set(config.events)].sort();
|
|
39
|
+
await (0, config_1.saveConfig)(config);
|
|
40
|
+
};
|
|
41
|
+
const handle = async (file) => {
|
|
42
|
+
try {
|
|
43
|
+
let content = await promises_1.default.readFile(file, "utf-8");
|
|
44
|
+
const parser = (0, router_1.detectParser)(file);
|
|
45
|
+
if (parser === "vue")
|
|
46
|
+
content = (0, vue_1.parseVue)(content);
|
|
47
|
+
if (parser === "svelte")
|
|
48
|
+
content = (0, svelte_1.parseSvelte)(content);
|
|
49
|
+
if (parser === "astro")
|
|
50
|
+
content = (0, astro_1.parseAstro)(content);
|
|
51
|
+
const source = project.createSourceFile(file, content, {
|
|
52
|
+
overwrite: true
|
|
53
|
+
});
|
|
54
|
+
const found = [
|
|
55
|
+
...(0, track_1.scanTrack)(source, config, aliases),
|
|
56
|
+
...(0, function_wrappers_1.scanFunctionWrappers)(source, config.functionWrappers ?? [], aliases),
|
|
57
|
+
...(0, component_wrappers_1.scanComponentWrappers)(source, config.wrappers ?? [], aliases)
|
|
58
|
+
];
|
|
59
|
+
for (const e of found) {
|
|
60
|
+
if (!e.value)
|
|
61
|
+
continue;
|
|
62
|
+
if (aliases[e.value] === "__skip__")
|
|
63
|
+
continue;
|
|
64
|
+
if (e.value in aliases)
|
|
65
|
+
continue;
|
|
66
|
+
if (seen.has(e.value))
|
|
67
|
+
continue;
|
|
68
|
+
seen.add(e.value);
|
|
69
|
+
if (!e.dynamic) {
|
|
70
|
+
config.events.push(e.value);
|
|
71
|
+
console.log(chalk_1.default.green(`+ ${e.value}`));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.log(chalk_1.default.yellow(`Dynamic: ${e.value}`));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
project.removeSourceFile(source);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
console.log(chalk_1.default.gray(`skip: ${file}`));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const watcher = chokidar_1.default.watch(config.sync.include, {
|
|
84
|
+
ignored: [
|
|
85
|
+
...config.sync.exclude,
|
|
86
|
+
"**/*.log",
|
|
87
|
+
"**/*.tmp",
|
|
88
|
+
"**/*.swp"
|
|
89
|
+
],
|
|
90
|
+
ignoreInitial: true
|
|
91
|
+
});
|
|
92
|
+
watcher.on("change", (file) => {
|
|
93
|
+
queue.add(file);
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
timer = setTimeout(processQueue, 200);
|
|
96
|
+
});
|
|
97
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -42,28 +42,32 @@ program
|
|
|
42
42
|
.version("0.0.1");
|
|
43
43
|
program
|
|
44
44
|
.command("init")
|
|
45
|
-
.description("Initialize Eventra")
|
|
46
45
|
.action(async () => {
|
|
47
46
|
const { init } = await Promise.resolve().then(() => __importStar(require("./commands/init")));
|
|
48
47
|
await init();
|
|
49
48
|
});
|
|
50
49
|
program
|
|
51
50
|
.command("sync")
|
|
52
|
-
.description("Sync events")
|
|
53
51
|
.action(async () => {
|
|
54
52
|
const { sync } = await Promise.resolve().then(() => __importStar(require("./commands/sync")));
|
|
55
53
|
await sync();
|
|
56
54
|
});
|
|
57
55
|
program
|
|
58
56
|
.command("check")
|
|
59
|
-
.
|
|
60
|
-
.action(async () => {
|
|
57
|
+
.option("--fix", "auto fix issues")
|
|
58
|
+
.action(async (opts) => {
|
|
61
59
|
const { check } = await Promise.resolve().then(() => __importStar(require("./commands/check")));
|
|
62
|
-
await check();
|
|
60
|
+
await check({ fix: opts.fix });
|
|
61
|
+
});
|
|
62
|
+
program
|
|
63
|
+
.command("watch")
|
|
64
|
+
.description("Watch files and detect events in real-time")
|
|
65
|
+
.action(async () => {
|
|
66
|
+
const { watch } = await Promise.resolve().then(() => __importStar(require("./commands/watch")));
|
|
67
|
+
await watch();
|
|
63
68
|
});
|
|
64
69
|
program
|
|
65
70
|
.command("send")
|
|
66
|
-
.description("Send events")
|
|
67
71
|
.action(async () => {
|
|
68
72
|
const { send } = await Promise.resolve().then(() => __importStar(require("./commands/send")));
|
|
69
73
|
await send();
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectAliases = detectAliases;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
function detectAliases(source) {
|
|
6
|
+
const aliases = {};
|
|
7
|
+
const vars = source.getDescendantsOfKind(ts_morph_1.SyntaxKind.VariableDeclaration);
|
|
8
|
+
for (const v of vars) {
|
|
9
|
+
const name = v.getName();
|
|
10
|
+
const init = v.getInitializer();
|
|
11
|
+
if (!init)
|
|
12
|
+
continue;
|
|
13
|
+
// const A = "event"
|
|
14
|
+
if (ts_morph_1.Node.isStringLiteral(init)) {
|
|
15
|
+
aliases[name] = init.getLiteralText();
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
// const A = `event`
|
|
19
|
+
if (init.getKind() === ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
20
|
+
aliases[name] = init.getText().replace(/`/g, "");
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
// const EVENTS = { CLICK: "click" }
|
|
24
|
+
if (ts_morph_1.Node.isObjectLiteralExpression(init)) {
|
|
25
|
+
for (const p of init.getProperties()) {
|
|
26
|
+
if (!ts_morph_1.Node.isPropertyAssignment(p))
|
|
27
|
+
continue;
|
|
28
|
+
const key = p.getName();
|
|
29
|
+
const val = p.getInitializer();
|
|
30
|
+
if (!val)
|
|
31
|
+
continue;
|
|
32
|
+
if (ts_morph_1.Node.isStringLiteral(val)) {
|
|
33
|
+
aliases[`${name}.${key}`] = val.getLiteralText();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return aliases;
|
|
39
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectWrappers = detectWrappers;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
function detectWrappers(source) {
|
|
6
|
+
return {
|
|
7
|
+
functions: detectFunctionWrappers(source),
|
|
8
|
+
components: detectComponentWrappers(source)
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
// FUNCTIONS
|
|
12
|
+
function detectFunctionWrappers(source) {
|
|
13
|
+
const result = new Map();
|
|
14
|
+
const functions = [
|
|
15
|
+
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.FunctionDeclaration),
|
|
16
|
+
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.ArrowFunction),
|
|
17
|
+
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.FunctionExpression)
|
|
18
|
+
];
|
|
19
|
+
for (const fn of functions) {
|
|
20
|
+
const body = fn.getBody();
|
|
21
|
+
if (!body)
|
|
22
|
+
continue;
|
|
23
|
+
const calls = body.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
|
|
24
|
+
for (const call of calls) {
|
|
25
|
+
if (!isTrackCall(call))
|
|
26
|
+
continue;
|
|
27
|
+
const name = getFunctionName(fn);
|
|
28
|
+
if (!name)
|
|
29
|
+
continue;
|
|
30
|
+
const arg = call.getArguments()[0];
|
|
31
|
+
let eventField;
|
|
32
|
+
if (arg && ts_morph_1.Node.isObjectLiteralExpression(arg)) {
|
|
33
|
+
const prop = arg.getProperties()[0];
|
|
34
|
+
if (prop && ts_morph_1.Node.isPropertyAssignment(prop)) {
|
|
35
|
+
eventField = prop.getName();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
result.set(name, { name, event: eventField });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return [...result.values()];
|
|
42
|
+
}
|
|
43
|
+
function isTrackCall(call) {
|
|
44
|
+
const expr = call.getExpression();
|
|
45
|
+
if (ts_morph_1.Node.isIdentifier(expr)) {
|
|
46
|
+
return expr.getText() === "track";
|
|
47
|
+
}
|
|
48
|
+
if (ts_morph_1.Node.isPropertyAccessExpression(expr)) {
|
|
49
|
+
return expr.getName() === "track";
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
function getFunctionName(fn) {
|
|
54
|
+
if (ts_morph_1.Node.isFunctionDeclaration(fn)) {
|
|
55
|
+
return fn.getName() ?? null;
|
|
56
|
+
}
|
|
57
|
+
const varDecl = fn.getFirstAncestorByKind(ts_morph_1.SyntaxKind.VariableDeclaration);
|
|
58
|
+
return varDecl?.getName() ?? null;
|
|
59
|
+
}
|
|
60
|
+
// COMPONENTS
|
|
61
|
+
function detectComponentWrappers(source) {
|
|
62
|
+
const result = new Map();
|
|
63
|
+
const elements = [
|
|
64
|
+
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxOpeningElement),
|
|
65
|
+
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxSelfClosingElement)
|
|
66
|
+
];
|
|
67
|
+
for (const el of elements) {
|
|
68
|
+
const name = el.getTagNameNode().getText();
|
|
69
|
+
for (const attr of el.getAttributes()) {
|
|
70
|
+
const a = attr.asKind(ts_morph_1.SyntaxKind.JsxAttribute);
|
|
71
|
+
if (!a)
|
|
72
|
+
continue;
|
|
73
|
+
const prop = a.getNameNode().getText();
|
|
74
|
+
const val = a.getInitializer();
|
|
75
|
+
if (!val)
|
|
76
|
+
continue;
|
|
77
|
+
if (ts_morph_1.Node.isStringLiteral(val) ||
|
|
78
|
+
ts_morph_1.Node.isJsxExpression(val)) {
|
|
79
|
+
result.set(name, { name, prop });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return [...result.values()];
|
|
84
|
+
}
|
package/dist/utils/extract.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.extractExpression = extractExpression;
|
|
4
4
|
const ts_morph_1 = require("ts-morph");
|
|
5
|
-
function extractExpression(expr) {
|
|
5
|
+
function extractExpression(expr, aliases) {
|
|
6
6
|
// "event"
|
|
7
7
|
if (ts_morph_1.Node.isStringLiteral(expr)) {
|
|
8
8
|
return {
|
|
@@ -11,124 +11,44 @@ function extractExpression(expr) {
|
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
// `event`
|
|
14
|
-
if (expr.getKind() ===
|
|
15
|
-
ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
14
|
+
if (expr.getKind() === ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
16
15
|
return {
|
|
17
|
-
values: [
|
|
18
|
-
expr.getText().replace(/`/g, "")
|
|
19
|
-
],
|
|
16
|
+
values: [expr.getText().replace(/`/g, "")],
|
|
20
17
|
dynamic: false
|
|
21
18
|
};
|
|
22
19
|
}
|
|
23
|
-
//
|
|
20
|
+
// IDENTIFIER
|
|
24
21
|
if (ts_morph_1.Node.isIdentifier(expr)) {
|
|
25
22
|
const name = expr.getText();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (decl && ts_morph_1.Node.isVariableDeclaration(decl)) {
|
|
32
|
-
const initializer = decl.getInitializer();
|
|
33
|
-
// const TEST = "event"
|
|
34
|
-
if (initializer &&
|
|
35
|
-
ts_morph_1.Node.isStringLiteral(initializer)) {
|
|
36
|
-
return {
|
|
37
|
-
values: [initializer.getLiteralText()],
|
|
38
|
-
dynamic: false
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
// const TEST = `event`
|
|
42
|
-
if (initializer &&
|
|
43
|
-
initializer.getKind() ===
|
|
44
|
-
ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
45
|
-
return {
|
|
46
|
-
values: [
|
|
47
|
-
initializer.getText().replace(/`/g, "")
|
|
48
|
-
],
|
|
49
|
-
dynamic: false
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
}
|
|
23
|
+
if (name in aliases) {
|
|
24
|
+
return {
|
|
25
|
+
values: [aliases[name]],
|
|
26
|
+
dynamic: false
|
|
27
|
+
};
|
|
53
28
|
}
|
|
54
29
|
return {
|
|
55
30
|
values: [name],
|
|
56
31
|
dynamic: true
|
|
57
32
|
};
|
|
58
33
|
}
|
|
59
|
-
//
|
|
34
|
+
// PROPERTY ACCESS
|
|
60
35
|
if (ts_morph_1.Node.isPropertyAccessExpression(expr)) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const decl = defs[0]?.getDeclarationNode();
|
|
68
|
-
// const EVENTS = { CLICK: "event" }
|
|
69
|
-
if (decl && ts_morph_1.Node.isVariableDeclaration(decl)) {
|
|
70
|
-
const init = decl.getInitializer();
|
|
71
|
-
if (init && ts_morph_1.Node.isObjectLiteralExpression(init)) {
|
|
72
|
-
const prop = init.getProperty(propName);
|
|
73
|
-
if (prop &&
|
|
74
|
-
ts_morph_1.Node.isPropertyAssignment(prop)) {
|
|
75
|
-
const value = prop.getInitializer();
|
|
76
|
-
if (value &&
|
|
77
|
-
ts_morph_1.Node.isStringLiteral(value)) {
|
|
78
|
-
return {
|
|
79
|
-
values: [value.getLiteralText()],
|
|
80
|
-
dynamic: false
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
// fallback
|
|
87
|
-
if (decl && ts_morph_1.Node.isPropertyAssignment(decl)) {
|
|
88
|
-
const initializer = decl.getInitializer();
|
|
89
|
-
if (initializer &&
|
|
90
|
-
ts_morph_1.Node.isStringLiteral(initializer)) {
|
|
91
|
-
return {
|
|
92
|
-
values: [initializer.getLiteralText()],
|
|
93
|
-
dynamic: false
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
}
|
|
36
|
+
const name = expr.getText();
|
|
37
|
+
if (name in aliases) {
|
|
38
|
+
return {
|
|
39
|
+
values: [aliases[name]],
|
|
40
|
+
dynamic: false
|
|
41
|
+
};
|
|
97
42
|
}
|
|
98
43
|
return {
|
|
99
|
-
values: [
|
|
100
|
-
dynamic: true
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
// ternary (a ? b : c)
|
|
104
|
-
if (ts_morph_1.Node.isConditionalExpression(expr)) {
|
|
105
|
-
const values = [];
|
|
106
|
-
const whenTrue = extractExpression(expr.getWhenTrue());
|
|
107
|
-
const whenFalse = extractExpression(expr.getWhenFalse());
|
|
108
|
-
if (whenTrue)
|
|
109
|
-
values.push(...whenTrue.values);
|
|
110
|
-
if (whenFalse)
|
|
111
|
-
values.push(...whenFalse.values);
|
|
112
|
-
return {
|
|
113
|
-
values,
|
|
44
|
+
values: [name],
|
|
114
45
|
dynamic: true
|
|
115
46
|
};
|
|
116
47
|
}
|
|
117
48
|
// template `${}`
|
|
118
49
|
if (ts_morph_1.Node.isTemplateExpression(expr)) {
|
|
119
50
|
return {
|
|
120
|
-
values: [
|
|
121
|
-
expr.getText().replace(/`/g, "")
|
|
122
|
-
],
|
|
123
|
-
dynamic: true
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
// call (fn())
|
|
127
|
-
if (ts_morph_1.Node.isCallExpression(expr)) {
|
|
128
|
-
return {
|
|
129
|
-
values: [
|
|
130
|
-
expr.getExpression().getText()
|
|
131
|
-
],
|
|
51
|
+
values: [expr.getText()],
|
|
132
52
|
dynamic: true
|
|
133
53
|
};
|
|
134
54
|
}
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.scanComponentWrappers = scanComponentWrappers;
|
|
4
4
|
const ts_morph_1 = require("ts-morph");
|
|
5
5
|
const extract_1 = require("../extract");
|
|
6
|
-
function scanComponentWrappers(source, wrappers) {
|
|
7
|
-
const events = new
|
|
6
|
+
function scanComponentWrappers(source, wrappers, aliases) {
|
|
7
|
+
const events = new Map();
|
|
8
8
|
const elements = [
|
|
9
9
|
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxOpeningElement),
|
|
10
10
|
...source.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxSelfClosingElement)
|
|
@@ -17,12 +17,9 @@ function scanComponentWrappers(source, wrappers) {
|
|
|
17
17
|
for (const wrapper of wrappers) {
|
|
18
18
|
if (name !== wrapper.name.toLowerCase())
|
|
19
19
|
continue;
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
// ❗ NO spread props
|
|
23
|
-
if (ts_morph_1.Node.isJsxSpreadAttribute(attr)) {
|
|
20
|
+
for (const attr of el.getAttributes()) {
|
|
21
|
+
if (ts_morph_1.Node.isJsxSpreadAttribute(attr))
|
|
24
22
|
continue;
|
|
25
|
-
}
|
|
26
23
|
const attrNode = attr.asKind(ts_morph_1.SyntaxKind.JsxAttribute);
|
|
27
24
|
if (!attrNode)
|
|
28
25
|
continue;
|
|
@@ -35,36 +32,42 @@ function scanComponentWrappers(source, wrappers) {
|
|
|
35
32
|
const init = attrNode.getInitializer();
|
|
36
33
|
// <Button event />
|
|
37
34
|
if (!init) {
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
const value = key;
|
|
36
|
+
const k = `${value}:true`;
|
|
37
|
+
events.set(k, {
|
|
38
|
+
value,
|
|
40
39
|
dynamic: true
|
|
41
40
|
});
|
|
42
41
|
continue;
|
|
43
42
|
}
|
|
44
|
-
//
|
|
43
|
+
// <Button event="click" />
|
|
45
44
|
if (ts_morph_1.Node.isStringLiteral(init)) {
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
const value = init.getLiteralText();
|
|
46
|
+
const k = `${value}:false`;
|
|
47
|
+
events.set(k, {
|
|
48
|
+
value,
|
|
48
49
|
dynamic: false
|
|
49
50
|
});
|
|
50
51
|
continue;
|
|
51
52
|
}
|
|
52
|
-
//
|
|
53
|
+
// <Button event={...} />
|
|
53
54
|
if (ts_morph_1.Node.isJsxExpression(init)) {
|
|
54
55
|
const expr = init.getExpression();
|
|
55
56
|
if (!expr)
|
|
56
57
|
continue;
|
|
57
|
-
const result = (0, extract_1.extractExpression)(expr);
|
|
58
|
+
const result = (0, extract_1.extractExpression)(expr, aliases);
|
|
58
59
|
if (!result)
|
|
59
60
|
continue;
|
|
60
|
-
result.values
|
|
61
|
-
value
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
for (const value of result.values) {
|
|
62
|
+
const k = `${value}:${result.dynamic}`;
|
|
63
|
+
events.set(k, {
|
|
64
|
+
value,
|
|
65
|
+
dynamic: result.dynamic
|
|
66
|
+
});
|
|
67
|
+
}
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
|
-
return events;
|
|
72
|
+
return [...events.values()];
|
|
70
73
|
}
|