@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
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.scanFunctionWrappers = scanFunctionWrappers;
|
|
4
4
|
const ts_morph_1 = require("ts-morph");
|
|
5
5
|
const extract_1 = require("../extract");
|
|
6
|
-
function scanFunctionWrappers(source, wrappers) {
|
|
7
|
-
const events = new
|
|
6
|
+
function scanFunctionWrappers(source, wrappers, aliases) {
|
|
7
|
+
const events = new Map();
|
|
8
8
|
const calls = source.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
|
|
9
9
|
for (const call of calls) {
|
|
10
10
|
const name = getFunctionName(call);
|
|
@@ -13,13 +13,16 @@ function scanFunctionWrappers(source, wrappers) {
|
|
|
13
13
|
for (const wrapper of wrappers) {
|
|
14
14
|
if (wrapper.name !== name)
|
|
15
15
|
continue;
|
|
16
|
-
const results = extractEventFromArgs(call, wrapper.event);
|
|
16
|
+
const results = extractEventFromArgs(call, wrapper.event, aliases);
|
|
17
17
|
if (!results)
|
|
18
18
|
continue;
|
|
19
|
-
|
|
19
|
+
for (const r of results) {
|
|
20
|
+
const key = `${r.value}:${r.dynamic}`;
|
|
21
|
+
events.set(key, r);
|
|
22
|
+
}
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
|
-
return events;
|
|
25
|
+
return [...events.values()];
|
|
23
26
|
}
|
|
24
27
|
function getFunctionName(call) {
|
|
25
28
|
const expression = call.getExpression();
|
|
@@ -35,21 +38,18 @@ function getDeepName(node) {
|
|
|
35
38
|
let current = node;
|
|
36
39
|
let name = "";
|
|
37
40
|
while (ts_morph_1.Node.isPropertyAccessExpression(current)) {
|
|
38
|
-
name =
|
|
39
|
-
|
|
40
|
-
current =
|
|
41
|
-
current.getExpression();
|
|
41
|
+
name = current.getName();
|
|
42
|
+
current = current.getExpression();
|
|
42
43
|
}
|
|
43
44
|
return name;
|
|
44
45
|
}
|
|
45
|
-
function extractEventFromArgs(call, event) {
|
|
46
|
+
function extractEventFromArgs(call, event, aliases) {
|
|
46
47
|
const args = call.getArguments();
|
|
47
48
|
const events = [];
|
|
48
|
-
for (
|
|
49
|
-
const arg = args[i];
|
|
49
|
+
for (const arg of args) {
|
|
50
50
|
// track("event")
|
|
51
51
|
if (!event) {
|
|
52
|
-
const result = (0, extract_1.extractExpression)(arg);
|
|
52
|
+
const result = (0, extract_1.extractExpression)(arg, aliases);
|
|
53
53
|
if (!result)
|
|
54
54
|
continue;
|
|
55
55
|
result.values.forEach((value) => events.push({
|
|
@@ -57,7 +57,7 @@ function extractEventFromArgs(call, event) {
|
|
|
57
57
|
dynamic: result.dynamic
|
|
58
58
|
}));
|
|
59
59
|
}
|
|
60
|
-
// track({event})
|
|
60
|
+
// track({ event })
|
|
61
61
|
if (event) {
|
|
62
62
|
const obj = arg.asKind(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
|
|
63
63
|
if (!obj)
|
|
@@ -69,7 +69,7 @@ function extractEventFromArgs(call, event) {
|
|
|
69
69
|
const init = prop.getInitializer();
|
|
70
70
|
if (!init)
|
|
71
71
|
continue;
|
|
72
|
-
const result = (0, extract_1.extractExpression)(init);
|
|
72
|
+
const result = (0, extract_1.extractExpression)(init, aliases);
|
|
73
73
|
if (!result)
|
|
74
74
|
continue;
|
|
75
75
|
result.values.forEach((value) => events.push({
|
|
@@ -79,7 +79,5 @@ function extractEventFromArgs(call, event) {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
return events.length
|
|
83
|
-
? events
|
|
84
|
-
: null;
|
|
82
|
+
return events.length ? events : null;
|
|
85
83
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.scanTrack = scanTrack;
|
|
4
7
|
const ts_morph_1 = require("ts-morph");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
5
9
|
const extract_1 = require("../extract");
|
|
6
|
-
function scanTrack(source, config) {
|
|
7
|
-
const events = new
|
|
10
|
+
function scanTrack(source, config, aliases) {
|
|
11
|
+
const events = new Map();
|
|
8
12
|
const calls = source.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
|
|
9
13
|
for (const call of calls) {
|
|
10
14
|
const expr = call.getExpression();
|
|
@@ -19,6 +23,7 @@ function scanTrack(source, config) {
|
|
|
19
23
|
}
|
|
20
24
|
if (!isTrack)
|
|
21
25
|
continue;
|
|
26
|
+
// ❗ skip wrapper functions
|
|
22
27
|
const func = call.getFirstAncestorByKind(ts_morph_1.SyntaxKind.FunctionDeclaration) ||
|
|
23
28
|
call.getFirstAncestorByKind(ts_morph_1.SyntaxKind.ArrowFunction) ||
|
|
24
29
|
call.getFirstAncestorByKind(ts_morph_1.SyntaxKind.FunctionExpression);
|
|
@@ -40,13 +45,20 @@ function scanTrack(source, config) {
|
|
|
40
45
|
const arg = call.getArguments()[0];
|
|
41
46
|
if (!arg)
|
|
42
47
|
continue;
|
|
43
|
-
const result = (0, extract_1.extractExpression)(arg);
|
|
48
|
+
const result = (0, extract_1.extractExpression)(arg, aliases);
|
|
44
49
|
if (!result)
|
|
45
50
|
continue;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
const line = call.getStartLineNumber();
|
|
52
|
+
const file = path_1.default.relative(process.cwd(), source.getFilePath());
|
|
53
|
+
for (const value of result.values) {
|
|
54
|
+
const key = `${value}:${file}:${line}`;
|
|
55
|
+
events.set(key, {
|
|
56
|
+
value,
|
|
57
|
+
dynamic: result.dynamic,
|
|
58
|
+
file,
|
|
59
|
+
line
|
|
60
|
+
});
|
|
61
|
+
}
|
|
50
62
|
}
|
|
51
|
-
return events;
|
|
63
|
+
return [...events.values()];
|
|
52
64
|
}
|
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.19",
|
|
4
4
|
"description": "Eventra CLI",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"chalk": "^4.1.2",
|
|
23
|
+
"chokidar": "^5.0.0",
|
|
23
24
|
"commander": "^11.0.0",
|
|
24
25
|
"fast-glob": "^3.3.3",
|
|
25
26
|
"fs-extra": "^11.2.0",
|
package/src/commands/check.ts
CHANGED
|
@@ -2,8 +2,9 @@ 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
|
-
import { loadConfig } from "../utils/config";
|
|
7
|
+
import { loadConfig, saveConfig } from "../utils/config";
|
|
7
8
|
|
|
8
9
|
import { detectParser } from "../utils/parsers/router";
|
|
9
10
|
import { parseVue } from "../utils/parsers/vue";
|
|
@@ -16,7 +17,7 @@ import { scanComponentWrappers } from "../utils/scanners/component-wrappers";
|
|
|
16
17
|
|
|
17
18
|
import { ExtractedEvent } from "../types";
|
|
18
19
|
|
|
19
|
-
export async function check() {
|
|
20
|
+
export async function check({ fix = false }: { fix?: boolean }) {
|
|
20
21
|
const config = await loadConfig();
|
|
21
22
|
|
|
22
23
|
if (!config) {
|
|
@@ -29,11 +30,11 @@ export async function check() {
|
|
|
29
30
|
const project = new Project();
|
|
30
31
|
|
|
31
32
|
const knownEvents = new Set(config.events ?? []);
|
|
32
|
-
const aliases = config.aliases ?? {};
|
|
33
|
+
const aliases = { ...(config.aliases ?? {}) };
|
|
33
34
|
|
|
34
|
-
const foundEvents = new
|
|
35
|
-
const newEvents = new
|
|
36
|
-
const unresolvedDynamic = new
|
|
35
|
+
const foundEvents = new Map<string, ExtractedEvent>();
|
|
36
|
+
const newEvents = new Map<string, ExtractedEvent>();
|
|
37
|
+
const unresolvedDynamic = new Map<string, ExtractedEvent>();
|
|
37
38
|
|
|
38
39
|
const files = await fg(config.sync.include, {
|
|
39
40
|
ignore: config.sync.exclude
|
|
@@ -41,132 +42,156 @@ export async function check() {
|
|
|
41
42
|
|
|
42
43
|
for (const file of files) {
|
|
43
44
|
try {
|
|
44
|
-
// skip huge files
|
|
45
45
|
const stat = await fs.stat(file);
|
|
46
|
+
|
|
46
47
|
if (stat.size > 2 * 1024 * 1024) {
|
|
47
|
-
console.log(chalk.gray(`Skipped large file: ${file}`));
|
|
48
48
|
continue;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
const parser = detectParser(file);
|
|
52
|
-
|
|
53
52
|
let content = await fs.readFile(file, "utf-8");
|
|
54
53
|
|
|
55
54
|
if (parser === "vue") content = parseVue(content);
|
|
56
55
|
if (parser === "svelte") content = parseSvelte(content);
|
|
57
56
|
if (parser === "astro") content = parseAstro(content);
|
|
58
57
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const source = project.createSourceFile(
|
|
63
|
-
virtualFile,
|
|
64
|
-
content,
|
|
65
|
-
{ overwrite: true }
|
|
66
|
-
);
|
|
58
|
+
const source = project.createSourceFile(file, content, {
|
|
59
|
+
overwrite: true
|
|
60
|
+
});
|
|
67
61
|
|
|
68
62
|
const found: ExtractedEvent[] = [
|
|
69
|
-
...scanTrack(source, config),
|
|
70
|
-
...scanFunctionWrappers(
|
|
71
|
-
|
|
72
|
-
config.functionWrappers ?? []
|
|
73
|
-
),
|
|
74
|
-
...scanComponentWrappers(
|
|
75
|
-
source,
|
|
76
|
-
config.wrappers ?? []
|
|
77
|
-
)
|
|
63
|
+
...scanTrack(source, config, aliases),
|
|
64
|
+
...scanFunctionWrappers(source, config.functionWrappers ?? [], aliases),
|
|
65
|
+
...scanComponentWrappers(source, config.wrappers ?? [], aliases)
|
|
78
66
|
];
|
|
79
67
|
|
|
80
68
|
for (const event of found) {
|
|
81
69
|
const { value, dynamic } = event;
|
|
82
|
-
|
|
83
70
|
if (!value) continue;
|
|
84
71
|
|
|
85
|
-
//
|
|
86
|
-
if (aliases[value] === "__skip__")
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
72
|
+
// skip
|
|
73
|
+
if (aliases[value] === "__skip__") continue;
|
|
89
74
|
|
|
90
75
|
// alias resolve
|
|
91
|
-
if (aliases
|
|
92
|
-
foundEvents.
|
|
76
|
+
if (value in aliases) {
|
|
77
|
+
foundEvents.set(aliases[value], {
|
|
78
|
+
...event,
|
|
79
|
+
value: aliases[value]
|
|
80
|
+
});
|
|
93
81
|
continue;
|
|
94
82
|
}
|
|
95
83
|
|
|
96
|
-
// dynamic without alias
|
|
97
84
|
if (dynamic) {
|
|
98
|
-
unresolvedDynamic.
|
|
85
|
+
unresolvedDynamic.set(value, event);
|
|
99
86
|
continue;
|
|
100
87
|
}
|
|
101
88
|
|
|
102
|
-
|
|
103
|
-
foundEvents.add(value);
|
|
89
|
+
foundEvents.set(value, event);
|
|
104
90
|
}
|
|
105
91
|
|
|
106
|
-
// clear memory
|
|
107
92
|
project.removeSourceFile(source);
|
|
108
93
|
|
|
109
94
|
} catch {
|
|
110
|
-
console.log(
|
|
111
|
-
chalk.gray(`Skipped file (error): ${file}`)
|
|
112
|
-
);
|
|
95
|
+
console.log(chalk.gray(`Skipped: ${file}`));
|
|
113
96
|
}
|
|
114
97
|
}
|
|
115
98
|
|
|
116
|
-
// find new
|
|
117
|
-
for (const event of foundEvents) {
|
|
118
|
-
if (!knownEvents.has(
|
|
119
|
-
newEvents.
|
|
99
|
+
// find new
|
|
100
|
+
for (const [key, event] of foundEvents) {
|
|
101
|
+
if (!knownEvents.has(key)) {
|
|
102
|
+
newEvents.set(key, event);
|
|
120
103
|
}
|
|
121
104
|
}
|
|
122
105
|
|
|
123
|
-
|
|
106
|
+
// FIX MODE
|
|
107
|
+
if (fix) {
|
|
108
|
+
console.log(chalk.yellow("\nFix mode\n"));
|
|
124
109
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
110
|
+
// add new events
|
|
111
|
+
for (const [name] of newEvents) {
|
|
112
|
+
config.events.push(name);
|
|
113
|
+
console.log(chalk.green(`+ ${name}`));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// resolve dynamic
|
|
117
|
+
for (const [value] of unresolvedDynamic) {
|
|
118
|
+
const { action } = await inquirer.prompt([
|
|
119
|
+
{
|
|
120
|
+
type: "list",
|
|
121
|
+
name: "action",
|
|
122
|
+
message: `Dynamic: ${value}`,
|
|
123
|
+
choices: [
|
|
124
|
+
{ name: "Alias", value: "alias" },
|
|
125
|
+
{ name: "Skip", value: "skip" }
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
if (action === "skip") {
|
|
131
|
+
aliases[value] = "__skip__";
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const { name } = await inquirer.prompt([
|
|
136
|
+
{
|
|
137
|
+
type: "input",
|
|
138
|
+
name: "name",
|
|
139
|
+
message: "Event name:"
|
|
140
|
+
}
|
|
141
|
+
]);
|
|
128
142
|
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
const normalized = name.trim().toLowerCase();
|
|
144
|
+
if (!normalized) continue;
|
|
145
|
+
|
|
146
|
+
aliases[value] = normalized;
|
|
147
|
+
config.events.push(normalized);
|
|
148
|
+
|
|
149
|
+
console.log(chalk.green(`${value} → ${normalized}`));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
config.aliases = Object.fromEntries(
|
|
153
|
+
Object.entries(aliases).sort()
|
|
131
154
|
);
|
|
132
155
|
|
|
133
|
-
[...
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
156
|
+
config.events = [...new Set(config.events)].sort();
|
|
157
|
+
|
|
158
|
+
await saveConfig(config);
|
|
159
|
+
|
|
160
|
+
console.log(chalk.green("\n✔ Fixed"));
|
|
161
|
+
return;
|
|
138
162
|
}
|
|
139
163
|
|
|
140
|
-
//
|
|
141
|
-
|
|
164
|
+
// NORMAL MODE
|
|
165
|
+
let hasError = false;
|
|
166
|
+
|
|
167
|
+
if (unresolvedDynamic.size) {
|
|
142
168
|
hasError = true;
|
|
143
169
|
|
|
144
|
-
console.log(
|
|
145
|
-
chalk.red("\nNew events detected:")
|
|
146
|
-
);
|
|
170
|
+
console.log(chalk.red("\nDynamic events:"));
|
|
147
171
|
|
|
148
|
-
|
|
149
|
-
.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
172
|
+
unresolvedDynamic.forEach((e) =>
|
|
173
|
+
console.log(
|
|
174
|
+
chalk.red(`- ${e.value} (${e.file}:${e.line})`)
|
|
175
|
+
)
|
|
176
|
+
);
|
|
153
177
|
}
|
|
154
178
|
|
|
155
|
-
if (
|
|
156
|
-
|
|
179
|
+
if (newEvents.size) {
|
|
180
|
+
hasError = true;
|
|
157
181
|
|
|
158
|
-
console.log(chalk.red("
|
|
182
|
+
console.log(chalk.red("\nNew events:"));
|
|
159
183
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
184
|
+
newEvents.forEach((e) =>
|
|
185
|
+
console.log(
|
|
186
|
+
chalk.red(`+ ${e.value} (${e.file}:${e.line})`)
|
|
163
187
|
)
|
|
164
188
|
);
|
|
189
|
+
}
|
|
165
190
|
|
|
191
|
+
if (hasError) {
|
|
192
|
+
console.log(chalk.red("\nEvent check failed"));
|
|
166
193
|
process.exit(1);
|
|
167
194
|
}
|
|
168
195
|
|
|
169
|
-
console.log(
|
|
170
|
-
chalk.green("\nAll events are valid")
|
|
171
|
-
);
|
|
196
|
+
console.log(chalk.green("\nAll good"));
|
|
172
197
|
}
|