@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
package/README.md
CHANGED
|
@@ -4,69 +4,68 @@
|
|
|
4
4
|
|
|
5
5
|
# Eventra CLI
|
|
6
6
|
|
|
7
|
-
[](https://www.npmjs.com/package/@eventra_dev/eventra-cli)
|
|
7
|
+
[](https://www.npmjs.com/package/@eventra_dev/eventra-cli)
|
|
8
|
+
[](https://www.npmjs.com/package/@eventra_dev/eventra-cli)
|
|
11
9
|
[](https://www.typescriptlang.org/)
|
|
12
10
|
|
|
13
|
-
Eventra CLI automatically discovers feature usage events in your
|
|
14
|
-
codebase and syncs them with Eventra.
|
|
11
|
+
Eventra CLI automatically discovers feature usage events in your codebase and syncs them with Eventra.
|
|
15
12
|
|
|
16
13
|
Eventra CLI helps you:
|
|
17
14
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
15
|
+
- Discover feature usage automatically
|
|
16
|
+
- Detect wrapper components
|
|
17
|
+
- Detect wrapper functions
|
|
18
|
+
- Keep events in sync
|
|
19
|
+
- Register features in Eventra
|
|
20
|
+
- Maintain consistent event naming
|
|
23
21
|
|
|
24
22
|
It is designed to be:
|
|
25
23
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
24
|
+
- framework-agnostic
|
|
25
|
+
- static analysis based
|
|
26
|
+
- zero runtime overhead
|
|
27
|
+
- production-safe
|
|
28
|
+
- backend + frontend compatible
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
---
|
|
32
31
|
|
|
33
32
|
# Installation
|
|
34
33
|
|
|
35
34
|
### npm
|
|
36
35
|
|
|
37
|
-
```
|
|
36
|
+
```bash
|
|
38
37
|
npm install -D @eventra_dev/eventra-cli
|
|
39
38
|
```
|
|
40
39
|
|
|
41
40
|
### pnpm
|
|
42
41
|
|
|
43
|
-
```
|
|
42
|
+
```bash
|
|
44
43
|
pnpm add -D @eventra_dev/eventra-cli
|
|
45
44
|
```
|
|
46
45
|
|
|
47
46
|
### yarn
|
|
48
47
|
|
|
49
|
-
```
|
|
48
|
+
```bash
|
|
50
49
|
yarn add -D @eventra_dev/eventra-cli
|
|
51
50
|
```
|
|
52
51
|
|
|
53
52
|
### npx
|
|
54
53
|
|
|
55
|
-
```
|
|
54
|
+
```bash
|
|
56
55
|
npx eventra init
|
|
57
56
|
```
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
---
|
|
60
59
|
|
|
61
60
|
# Quick Start
|
|
62
61
|
|
|
63
|
-
```
|
|
62
|
+
```bash
|
|
64
63
|
eventra init
|
|
65
64
|
eventra sync
|
|
66
65
|
eventra send
|
|
67
66
|
```
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
---
|
|
70
69
|
|
|
71
70
|
# Commands
|
|
72
71
|
|
|
@@ -74,60 +73,140 @@ eventra send
|
|
|
74
73
|
|
|
75
74
|
Creates `eventra.json` configuration file.
|
|
76
75
|
|
|
77
|
-
```
|
|
76
|
+
```bash
|
|
78
77
|
eventra init
|
|
79
78
|
```
|
|
80
79
|
|
|
81
|
-
|
|
80
|
+
---
|
|
82
81
|
|
|
83
82
|
## eventra sync
|
|
84
83
|
|
|
85
84
|
Scans your project and discovers events automatically.
|
|
86
85
|
|
|
87
|
-
|
|
86
|
+
### track() detection
|
|
87
|
+
|
|
88
|
+
```ts
|
|
88
89
|
tracker.track("feature_created")
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
```
|
|
92
|
+
```ts
|
|
93
|
+
track("user_signup")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### Component wrappers
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
92
101
|
<TrackedButton event="feature_created" />
|
|
93
102
|
```
|
|
94
103
|
|
|
95
|
-
```
|
|
104
|
+
```tsx
|
|
96
105
|
<MyComponent event="user_signup" />
|
|
97
106
|
```
|
|
98
107
|
|
|
99
|
-
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### Function wrappers
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
trackFeature("feature_created")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
analytics.trackFeature("user_signup")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
100
121
|
|
|
101
122
|
## eventra send
|
|
102
123
|
|
|
103
124
|
Send events to Eventra backend.
|
|
104
125
|
|
|
105
|
-
```
|
|
126
|
+
```bash
|
|
106
127
|
eventra send
|
|
107
128
|
```
|
|
108
129
|
|
|
109
|
-
|
|
130
|
+
New events are queued for processing and will appear in dashboard shortly.
|
|
131
|
+
|
|
132
|
+
Processing typically takes:
|
|
133
|
+
|
|
134
|
+
~1-2 minutes
|
|
135
|
+
|
|
136
|
+
This delay ensures reliable event ingestion and aggregation.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
# Configuration
|
|
141
|
+
|
|
142
|
+
Eventra CLI creates `eventra.json`
|
|
143
|
+
|
|
144
|
+
Example:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"apiKey": "",
|
|
149
|
+
"events": [],
|
|
150
|
+
"wrappers": [],
|
|
151
|
+
"functionWrappers": [],
|
|
152
|
+
"sync": {
|
|
153
|
+
"include": ["**/*.{ts,tsx,js,jsx}"],
|
|
154
|
+
"exclude": [
|
|
155
|
+
"node_modules",
|
|
156
|
+
"dist",
|
|
157
|
+
".next",
|
|
158
|
+
".git"
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
110
165
|
|
|
111
166
|
# Supported Frameworks
|
|
112
167
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
|
|
168
|
+
Frontend:
|
|
169
|
+
|
|
170
|
+
- React
|
|
171
|
+
- Next.js
|
|
172
|
+
- Vue
|
|
173
|
+
- Nuxt
|
|
174
|
+
- Svelte
|
|
175
|
+
- Astro
|
|
176
|
+
|
|
177
|
+
Backend:
|
|
178
|
+
|
|
179
|
+
- Node.js
|
|
180
|
+
- Express
|
|
181
|
+
- NestJS
|
|
182
|
+
- Fastify
|
|
183
|
+
- Hono
|
|
184
|
+
- Bun
|
|
185
|
+
- Deno
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
# How It Works
|
|
190
|
+
|
|
191
|
+
Eventra CLI:
|
|
192
|
+
|
|
193
|
+
1. Scans your codebase
|
|
194
|
+
2. Detects tracking calls
|
|
195
|
+
3. Detects wrapper components
|
|
196
|
+
4. Detects wrapper functions
|
|
197
|
+
5. Syncs discovered events
|
|
198
|
+
6. Registers events in Eventra
|
|
199
|
+
|
|
200
|
+
No runtime SDK required.
|
|
122
201
|
|
|
123
|
-
|
|
202
|
+
---
|
|
124
203
|
|
|
125
204
|
# Requirements
|
|
126
205
|
|
|
127
|
-
-
|
|
128
|
-
-
|
|
206
|
+
- Node.js 18+
|
|
207
|
+
- JavaScript / TypeScript project
|
|
129
208
|
|
|
130
|
-
|
|
209
|
+
---
|
|
131
210
|
|
|
132
211
|
# License
|
|
133
212
|
|
package/dist/commands/init.js
CHANGED
package/dist/commands/send.js
CHANGED
|
@@ -7,15 +7,17 @@ exports.send = send;
|
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
9
9
|
const config_1 = require("../utils/config");
|
|
10
|
+
const package_json_1 = __importDefault(require("../../package.json"));
|
|
10
11
|
const EVENTRA_ENDPOINT = process.env.EVENTRA_ENDPOINT ?? "";
|
|
11
|
-
const CLI_VERSION =
|
|
12
|
+
const CLI_VERSION = package_json_1.default.version;
|
|
12
13
|
async function send() {
|
|
13
|
-
|
|
14
|
+
const config = await (0, config_1.loadConfig)();
|
|
14
15
|
if (!config) {
|
|
15
16
|
console.log(chalk_1.default.red("eventra.json not found. Run 'eventra init'"));
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
19
|
let apiKey = config.apiKey;
|
|
20
|
+
// ask api key
|
|
19
21
|
if (!apiKey) {
|
|
20
22
|
const answers = await inquirer_1.default.prompt([
|
|
21
23
|
{
|
|
@@ -29,11 +31,21 @@ async function send() {
|
|
|
29
31
|
await (0, config_1.saveConfig)(config);
|
|
30
32
|
console.log(chalk_1.default.green("API key saved"));
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
// no events
|
|
35
|
+
if (!config.events?.length) {
|
|
33
36
|
console.log(chalk_1.default.yellow("No events found. Run 'eventra sync'"));
|
|
34
37
|
return;
|
|
35
38
|
}
|
|
36
|
-
|
|
39
|
+
if (!apiKey) {
|
|
40
|
+
console.log(chalk_1.default.red("API key required"));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!EVENTRA_ENDPOINT) {
|
|
44
|
+
console.log(chalk_1.default.red("EVENTRA_ENDPOINT not configured"));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.log("");
|
|
48
|
+
console.log(chalk_1.default.blue(`Sending ${config.events.length} events...`));
|
|
37
49
|
try {
|
|
38
50
|
const res = await fetch(EVENTRA_ENDPOINT, {
|
|
39
51
|
method: "POST",
|
|
@@ -50,18 +62,40 @@ async function send() {
|
|
|
50
62
|
}
|
|
51
63
|
})
|
|
52
64
|
});
|
|
53
|
-
if (res.
|
|
54
|
-
console.log(chalk_1.default.red(`
|
|
65
|
+
if (!res.ok) {
|
|
66
|
+
console.log(chalk_1.default.red(`Request failed (${res.status})`));
|
|
67
|
+
try {
|
|
68
|
+
const text = await res.text();
|
|
69
|
+
console.log(chalk_1.default.gray(text));
|
|
70
|
+
}
|
|
71
|
+
catch { }
|
|
55
72
|
return;
|
|
56
73
|
}
|
|
57
74
|
const data = await res.json();
|
|
58
75
|
console.log(chalk_1.default.green("Events registered successfully"));
|
|
76
|
+
// created
|
|
59
77
|
if (data.created?.length) {
|
|
60
78
|
console.log(chalk_1.default.green("\nNew events:"));
|
|
61
79
|
data.created.forEach((e) => console.log(chalk_1.default.green(`+ ${e}`)));
|
|
62
80
|
}
|
|
81
|
+
// existing
|
|
82
|
+
if (data.existing?.length) {
|
|
83
|
+
console.log(chalk_1.default.gray("\nExisting events:"));
|
|
84
|
+
data.existing.forEach((e) => console.log(chalk_1.default.gray(`• ${e}`)));
|
|
85
|
+
}
|
|
86
|
+
// processing notice
|
|
87
|
+
if (data.created?.length) {
|
|
88
|
+
console.log("");
|
|
89
|
+
console.log(chalk_1.default.yellow("Events queued for processing (~2 min)"));
|
|
90
|
+
console.log(chalk_1.default.gray("They will appear in dashboard shortly"));
|
|
91
|
+
}
|
|
92
|
+
console.log("");
|
|
93
|
+
console.log(chalk_1.default.gray(`Sent ${config.events.length} events`));
|
|
63
94
|
}
|
|
64
|
-
catch {
|
|
95
|
+
catch (err) {
|
|
65
96
|
console.log(chalk_1.default.red("Network error"));
|
|
97
|
+
if (err instanceof Error) {
|
|
98
|
+
console.log(chalk_1.default.gray(err.message));
|
|
99
|
+
}
|
|
66
100
|
}
|
|
67
101
|
}
|
package/dist/commands/sync.js
CHANGED
|
@@ -4,213 +4,46 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.sync = sync;
|
|
7
|
-
const ts_morph_1 = require("ts-morph");
|
|
8
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
9
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
-
const
|
|
8
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
9
|
+
const ts_morph_1 = require("ts-morph");
|
|
10
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
11
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");
|
|
12
19
|
async function sync() {
|
|
13
|
-
|
|
20
|
+
const config = await (0, config_1.loadConfig)();
|
|
14
21
|
if (!config) {
|
|
15
|
-
console.log(chalk_1.default.red("Run 'eventra init'
|
|
22
|
+
console.log(chalk_1.default.red("Run 'eventra init'"));
|
|
16
23
|
return;
|
|
17
24
|
}
|
|
18
|
-
const events = new Set();
|
|
19
|
-
const project = new ts_morph_1.Project();
|
|
20
25
|
console.log(chalk_1.default.blue("Scanning project..."));
|
|
26
|
+
const project = new ts_morph_1.Project();
|
|
27
|
+
const events = new Set();
|
|
21
28
|
const files = await (0, fast_glob_1.default)(config.sync.include, {
|
|
22
29
|
ignore: config.sync.exclude
|
|
23
30
|
});
|
|
24
|
-
// track()
|
|
25
31
|
for (const file of files) {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const eventArg = args[0];
|
|
39
|
-
if (!eventArg)
|
|
40
|
-
continue;
|
|
41
|
-
let event = null;
|
|
42
|
-
// "event"
|
|
43
|
-
if (eventArg.getKind() ===
|
|
44
|
-
ts_morph_1.SyntaxKind.StringLiteral) {
|
|
45
|
-
event =
|
|
46
|
-
eventArg
|
|
47
|
-
.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral)
|
|
48
|
-
.getLiteralText();
|
|
49
|
-
}
|
|
50
|
-
// `event`
|
|
51
|
-
if (eventArg.getKind() ===
|
|
52
|
-
ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
|
|
53
|
-
event =
|
|
54
|
-
eventArg
|
|
55
|
-
.asKindOrThrow(ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral)
|
|
56
|
-
.getLiteralText();
|
|
57
|
-
}
|
|
58
|
-
if (event) {
|
|
59
|
-
events.add(event);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
console.log(chalk_1.default.green(`Found ${events.size} track events`));
|
|
65
|
-
// wrappers setup
|
|
66
|
-
if (!config.wrappers.length) {
|
|
67
|
-
const { useWrapper } = await inquirer_1.default.prompt([
|
|
68
|
-
{
|
|
69
|
-
type: "confirm",
|
|
70
|
-
name: "useWrapper",
|
|
71
|
-
message: "Use wrapper components?",
|
|
72
|
-
default: true
|
|
73
|
-
}
|
|
74
|
-
]);
|
|
75
|
-
if (useWrapper) {
|
|
76
|
-
const wrappers = [];
|
|
77
|
-
let addMore = true;
|
|
78
|
-
while (addMore) {
|
|
79
|
-
const answers = await inquirer_1.default.prompt([
|
|
80
|
-
{
|
|
81
|
-
type: "input",
|
|
82
|
-
name: "name",
|
|
83
|
-
message: "Wrapper component name:"
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
type: "input",
|
|
87
|
-
name: "prop",
|
|
88
|
-
message: "Event prop name:"
|
|
89
|
-
}
|
|
90
|
-
]);
|
|
91
|
-
wrappers.push({
|
|
92
|
-
name: answers.name,
|
|
93
|
-
prop: answers.prop
|
|
94
|
-
});
|
|
95
|
-
const more = await inquirer_1.default.prompt([
|
|
96
|
-
{
|
|
97
|
-
type: "confirm",
|
|
98
|
-
name: "more",
|
|
99
|
-
message: "Add another wrapper?",
|
|
100
|
-
default: false
|
|
101
|
-
}
|
|
102
|
-
]);
|
|
103
|
-
addMore = more.more;
|
|
104
|
-
}
|
|
105
|
-
config.wrappers = wrappers;
|
|
106
|
-
}
|
|
32
|
+
const parser = (0, router_1.detectParser)(file);
|
|
33
|
+
let content = await promises_1.default.readFile(file, "utf-8");
|
|
34
|
+
if (parser === "vue")
|
|
35
|
+
content = (0, vue_1.parseVue)(content);
|
|
36
|
+
if (parser === "svelte")
|
|
37
|
+
content = (0, svelte_1.parseSvelte)(content);
|
|
38
|
+
if (parser === "astro")
|
|
39
|
+
content = (0, astro_1.parseAstro)(content);
|
|
40
|
+
const source = project.createSourceFile(file, content, { overwrite: true });
|
|
41
|
+
(0, track_1.scanTrack)(source).forEach((e) => events.add(e));
|
|
42
|
+
(0, function_wrappers_1.scanFunctionWrappers)(source, config.functionWrappers ?? []).forEach((e) => events.add(e));
|
|
43
|
+
(0, component_wrappers_1.scanComponentWrappers)(source, config.wrappers ?? []).forEach((e) => events.add(e));
|
|
107
44
|
}
|
|
108
|
-
// scan wrappers
|
|
109
|
-
if (config.wrappers.length) {
|
|
110
|
-
console.log(chalk_1.default.blue("Scanning wrappers..."));
|
|
111
|
-
for (const file of files) {
|
|
112
|
-
const sourceFile = project.addSourceFileAtPath(file);
|
|
113
|
-
const elements = [
|
|
114
|
-
...sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxOpeningElement),
|
|
115
|
-
...sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.JsxSelfClosingElement)
|
|
116
|
-
];
|
|
117
|
-
for (const element of elements) {
|
|
118
|
-
const tagName = element
|
|
119
|
-
.getTagNameNode()
|
|
120
|
-
.getText()
|
|
121
|
-
.toLowerCase();
|
|
122
|
-
for (const wrapper of config.wrappers) {
|
|
123
|
-
if (tagName !==
|
|
124
|
-
wrapper.name.toLowerCase())
|
|
125
|
-
continue;
|
|
126
|
-
const attrs = element.getAttributes();
|
|
127
|
-
for (const attr of attrs) {
|
|
128
|
-
if (attr.getKind() !==
|
|
129
|
-
ts_morph_1.SyntaxKind.JsxAttribute)
|
|
130
|
-
continue;
|
|
131
|
-
const attrNode = attr.asKind(ts_morph_1.SyntaxKind.JsxAttribute);
|
|
132
|
-
if (!attrNode)
|
|
133
|
-
continue;
|
|
134
|
-
const attrName = attrNode
|
|
135
|
-
.getNameNode()
|
|
136
|
-
.getText()
|
|
137
|
-
.toLowerCase();
|
|
138
|
-
if (attrName !==
|
|
139
|
-
wrapper.prop.toLowerCase())
|
|
140
|
-
continue;
|
|
141
|
-
const initializer = attrNode.getInitializer();
|
|
142
|
-
if (!initializer)
|
|
143
|
-
continue;
|
|
144
|
-
let value = null;
|
|
145
|
-
// event="signup"
|
|
146
|
-
if (initializer.getKind() ===
|
|
147
|
-
ts_morph_1.SyntaxKind.StringLiteral) {
|
|
148
|
-
value =
|
|
149
|
-
initializer
|
|
150
|
-
.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral)
|
|
151
|
-
.getLiteralText();
|
|
152
|
-
}
|
|
153
|
-
// event={"signup"}
|
|
154
|
-
if (initializer.getKind() ===
|
|
155
|
-
ts_morph_1.SyntaxKind.JsxExpression) {
|
|
156
|
-
const expr = initializer
|
|
157
|
-
.asKindOrThrow(ts_morph_1.SyntaxKind.JsxExpression)
|
|
158
|
-
.getExpression();
|
|
159
|
-
if (expr?.getKind() ===
|
|
160
|
-
ts_morph_1.SyntaxKind.StringLiteral) {
|
|
161
|
-
value =
|
|
162
|
-
expr
|
|
163
|
-
.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral)
|
|
164
|
-
.getLiteralText();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (value) {
|
|
168
|
-
events.add(value);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
// results
|
|
176
45
|
const list = [...events].sort();
|
|
177
|
-
console.log("");
|
|
178
|
-
console.log(chalk_1.default.green("Found events:"));
|
|
179
|
-
list.forEach((e) => console.log(chalk_1.default.gray(`- ${e}`)));
|
|
180
|
-
console.log("");
|
|
181
|
-
// diff
|
|
182
|
-
const previous = config.events ?? [];
|
|
183
|
-
const added = list.filter((e) => !previous.includes(e));
|
|
184
|
-
const removed = previous.filter((e) => !list.includes(e));
|
|
185
|
-
if (added.length || removed.length) {
|
|
186
|
-
console.log(chalk_1.default.blue("Changes:"));
|
|
187
|
-
if (added.length) {
|
|
188
|
-
console.log(chalk_1.default.green("New events:"));
|
|
189
|
-
added.forEach((e) => console.log(chalk_1.default.green(`+ ${e}`)));
|
|
190
|
-
}
|
|
191
|
-
if (removed.length) {
|
|
192
|
-
console.log(chalk_1.default.red("Removed events:"));
|
|
193
|
-
removed.forEach((e) => console.log(chalk_1.default.red(`- ${e}`)));
|
|
194
|
-
}
|
|
195
|
-
console.log("");
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
console.log(chalk_1.default.gray("No changes detected"));
|
|
199
|
-
}
|
|
200
|
-
// confirm
|
|
201
|
-
const { confirm } = await inquirer_1.default.prompt([
|
|
202
|
-
{
|
|
203
|
-
type: "confirm",
|
|
204
|
-
name: "confirm",
|
|
205
|
-
message: "Sync these events?",
|
|
206
|
-
default: true
|
|
207
|
-
}
|
|
208
|
-
]);
|
|
209
|
-
if (!confirm) {
|
|
210
|
-
console.log(chalk_1.default.yellow("Sync cancelled"));
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
46
|
config.events = list;
|
|
214
47
|
await (0, config_1.saveConfig)(config);
|
|
215
|
-
console.log(chalk_1.default.green(
|
|
48
|
+
console.log(chalk_1.default.green(`Found ${list.length} events`));
|
|
216
49
|
}
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/types.js
ADDED
package/dist/utils/config.js
CHANGED
|
@@ -15,8 +15,11 @@ function normalizeConfig(config) {
|
|
|
15
15
|
apiKey: config.apiKey ?? "",
|
|
16
16
|
events: config.events ?? [],
|
|
17
17
|
wrappers: config.wrappers ?? [],
|
|
18
|
+
functionWrappers: config.functionWrappers ?? [],
|
|
18
19
|
sync: config.sync ?? {
|
|
19
|
-
include: [
|
|
20
|
+
include: [
|
|
21
|
+
"**/*.{ts,tsx,js,jsx}"
|
|
22
|
+
],
|
|
20
23
|
exclude: [
|
|
21
24
|
"node_modules",
|
|
22
25
|
"dist",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractEvent = extractEvent;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
function extractEvent(call, path) {
|
|
6
|
+
const parts = path.split(".");
|
|
7
|
+
let node = call.getArguments()[Number(parts[0])];
|
|
8
|
+
if (!node)
|
|
9
|
+
return null;
|
|
10
|
+
for (let i = 1; i < parts.length; i++) {
|
|
11
|
+
if (ts_morph_1.Node.isObjectLiteralExpression(node)) {
|
|
12
|
+
const obj = node;
|
|
13
|
+
const prop = obj.getProperty(parts[i]);
|
|
14
|
+
if (!prop)
|
|
15
|
+
return null;
|
|
16
|
+
if (ts_morph_1.Node.isPropertyAssignment(prop)) {
|
|
17
|
+
const initializer = prop.getInitializer();
|
|
18
|
+
if (!initializer)
|
|
19
|
+
return null;
|
|
20
|
+
node = initializer;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (node &&
|
|
25
|
+
ts_morph_1.Node.isStringLiteral(node)) {
|
|
26
|
+
return node.getLiteralText();
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectParser = detectParser;
|
|
4
|
+
function detectParser(file) {
|
|
5
|
+
if (file.endsWith(".vue"))
|
|
6
|
+
return "vue";
|
|
7
|
+
if (file.endsWith(".svelte"))
|
|
8
|
+
return "svelte";
|
|
9
|
+
if (file.endsWith(".astro"))
|
|
10
|
+
return "astro";
|
|
11
|
+
return "ts";
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseVue = parseVue;
|
|
4
|
+
function parseVue(content) {
|
|
5
|
+
const template = content.match(/<template[\s\S]*?>([\s\S]*?)<\/template>/);
|
|
6
|
+
const script = content.match(/<script[\s\S]*?>([\s\S]*?)<\/script>/);
|
|
7
|
+
return ((template?.[1] ?? "") +
|
|
8
|
+
"\n" +
|
|
9
|
+
(script?.[1] ?? ""));
|
|
10
|
+
}
|