@eventra_dev/eventra-cli 0.0.4 → 0.0.6

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.
Files changed (40) hide show
  1. package/.github/workflows/release.yml +3 -0
  2. package/README.md +125 -44
  3. package/dist/commands/init.js +4 -1
  4. package/dist/commands/send.js +41 -7
  5. package/dist/commands/sync.js +35 -194
  6. package/dist/index.js +0 -0
  7. package/dist/types.js +2 -0
  8. package/dist/utils/config.js +4 -1
  9. package/dist/utils/extract.js +44 -0
  10. package/dist/utils/parsers/astro.js +6 -0
  11. package/dist/utils/parsers/router.js +12 -0
  12. package/dist/utils/parsers/svelte.js +6 -0
  13. package/dist/utils/parsers/vue.js +18 -0
  14. package/dist/utils/scanners/component-wrappers.js +55 -0
  15. package/dist/utils/scanners/function-wrappers.js +45 -0
  16. package/dist/utils/scanners/track.js +42 -0
  17. package/package.json +6 -4
  18. package/src/commands/init.ts +4 -1
  19. package/src/commands/send.ts +101 -17
  20. package/src/commands/sync.ts +66 -345
  21. package/src/types.ts +20 -0
  22. package/src/utils/config.ts +24 -7
  23. package/src/utils/extract.ts +74 -0
  24. package/src/utils/parsers/astro.ts +5 -0
  25. package/src/utils/parsers/router.ts +14 -0
  26. package/src/utils/parsers/svelte.ts +5 -0
  27. package/src/utils/parsers/vue.ts +25 -0
  28. package/src/utils/scanners/component-wrappers.ts +108 -0
  29. package/src/utils/scanners/function-wrappers.ts +98 -0
  30. package/src/utils/scanners/track.ts +84 -0
  31. package/tests/fixtures/backend/express/app.ts +78 -0
  32. package/tests/fixtures/backend/nest/service.ts +70 -0
  33. package/tests/fixtures/backend/node/index.ts +63 -0
  34. package/tests/fixtures/frontend/next/page.tsx +101 -0
  35. package/tests/fixtures/frontend/react/App.tsx +104 -0
  36. package/tests/fixtures/frontend/vue/App.vue +83 -0
  37. package/tests/fixtures/wrappers/component/test.tsx +62 -0
  38. package/tests/fixtures/wrappers/function/test.ts +60 -0
  39. package/tests/run.ts +120 -0
  40. package/tsconfig.json +2 -0
@@ -33,6 +33,9 @@ jobs:
33
33
  - name: Build CLI
34
34
  run: pnpm build
35
35
 
36
+ - name: Run tests
37
+ run: pnpm test
38
+
36
39
  - name: Publish to npm
37
40
  run: npm publish --access public
38
41
  env:
package/README.md CHANGED
@@ -4,69 +4,70 @@
4
4
 
5
5
  # Eventra CLI
6
6
 
7
- [![npm
8
- version](https://img.shields.io/npm/v/@eventra_dev/eventra-cli.svg)](https://www.npmjs.com/package/@eventra_dev/eventra-cli)
9
- [![npm
10
- downloads](https://img.shields.io/npm/dm/@eventra_dev/eventra-cli.svg)](https://www.npmjs.com/package/@eventra_dev/eventra-cli)
7
+ [![npm version](https://img.shields.io/npm/v/@eventra_dev/eventra-cli.svg)](https://www.npmjs.com/package/@eventra_dev/eventra-cli)
8
+ [![npm downloads](https://img.shields.io/npm/dm/@eventra_dev/eventra-cli.svg)](https://www.npmjs.com/package/@eventra_dev/eventra-cli)
11
9
  [![TypeScript](https://img.shields.io/badge/typescript-ready-blue.svg)](https://www.typescriptlang.org/)
10
+ [![Tests](https://github.com/and-1991/eventra-cli/actions/workflows/release.yml/badge.svg)]()
11
+ [![License](https://img.shields.io/npm/l/@eventra_dev/eventra-cli)]()
12
12
 
13
- Eventra CLI automatically discovers feature usage events in your
14
- codebase and syncs them with Eventra.
13
+ Eventra CLI automatically discovers feature usage events in your codebase and syncs them with Eventra.
15
14
 
16
15
  Eventra CLI helps you:
17
16
 
18
- - Discover feature usage automatically
19
- - Detect wrapper components
20
- - Keep events in sync
21
- - Register features in Eventra
22
- - Maintain consistent event naming
17
+ - Discover feature usage automatically
18
+ - Detect wrapper components
19
+ - Detect wrapper functions
20
+ - Keep events in sync
21
+ - Register features in Eventra
22
+ - Maintain consistent event naming
23
23
 
24
24
  It is designed to be:
25
25
 
26
- - framework-agnostic
27
- - static analysis based
28
- - zero runtime overhead
29
- - production-safe
26
+ - framework-agnostic
27
+ - static analysis based
28
+ - zero runtime overhead
29
+ - production-safe
30
+ - backend + frontend compatible
30
31
 
31
- ------------------------------------------------------------------------
32
+ ---
32
33
 
33
34
  # Installation
34
35
 
35
36
  ### npm
36
37
 
37
- ``` bash
38
+ ```bash
38
39
  npm install -D @eventra_dev/eventra-cli
39
40
  ```
40
41
 
41
42
  ### pnpm
42
43
 
43
- ``` bash
44
+ ```bash
44
45
  pnpm add -D @eventra_dev/eventra-cli
45
46
  ```
46
47
 
47
48
  ### yarn
48
49
 
49
- ``` bash
50
+ ```bash
50
51
  yarn add -D @eventra_dev/eventra-cli
51
52
  ```
52
53
 
53
54
  ### npx
54
55
 
55
- ``` bash
56
+ ```bash
56
57
  npx eventra init
57
58
  ```
58
59
 
59
- ------------------------------------------------------------------------
60
+ ---
60
61
 
61
62
  # Quick Start
62
63
 
63
- ``` bash
64
+ ```bash
64
65
  eventra init
65
66
  eventra sync
66
67
  eventra send
67
68
  ```
68
69
 
69
- ------------------------------------------------------------------------
70
+ ---
70
71
 
71
72
  # Commands
72
73
 
@@ -74,60 +75,140 @@ eventra send
74
75
 
75
76
  Creates `eventra.json` configuration file.
76
77
 
77
- ``` bash
78
+ ```bash
78
79
  eventra init
79
80
  ```
80
81
 
81
- ------------------------------------------------------------------------
82
+ ---
82
83
 
83
84
  ## eventra sync
84
85
 
85
86
  Scans your project and discovers events automatically.
86
87
 
87
- ``` ts
88
+ ### track() detection
89
+
90
+ ```ts
88
91
  tracker.track("feature_created")
89
92
  ```
90
93
 
91
- ``` tsx
94
+ ```ts
95
+ track("user_signup")
96
+ ```
97
+
98
+ ---
99
+
100
+ ### Component wrappers
101
+
102
+ ```tsx
92
103
  <TrackedButton event="feature_created" />
93
104
  ```
94
105
 
95
- ``` tsx
106
+ ```tsx
96
107
  <MyComponent event="user_signup" />
97
108
  ```
98
109
 
99
- ------------------------------------------------------------------------
110
+ ---
111
+
112
+ ### Function wrappers
113
+
114
+ ```ts
115
+ trackFeature("feature_created")
116
+ ```
117
+
118
+ ```ts
119
+ analytics.trackFeature("user_signup")
120
+ ```
121
+
122
+ ---
100
123
 
101
124
  ## eventra send
102
125
 
103
126
  Send events to Eventra backend.
104
127
 
105
- ``` bash
128
+ ```bash
106
129
  eventra send
107
130
  ```
108
131
 
109
- ------------------------------------------------------------------------
132
+ New events are queued for processing and will appear in dashboard shortly.
133
+
134
+ Processing typically takes:
135
+
136
+ ~1-2 minutes
137
+
138
+ This delay ensures reliable event ingestion and aggregation.
139
+
140
+ ---
141
+
142
+ # Configuration
143
+
144
+ Eventra CLI creates `eventra.json`
145
+
146
+ Example:
147
+
148
+ ```json
149
+ {
150
+ "apiKey": "",
151
+ "events": [],
152
+ "wrappers": [],
153
+ "functionWrappers": [],
154
+ "sync": {
155
+ "include": ["**/*.{ts,tsx,js,jsx}"],
156
+ "exclude": [
157
+ "node_modules",
158
+ "dist",
159
+ ".next",
160
+ ".git"
161
+ ]
162
+ }
163
+ }
164
+ ```
165
+
166
+ ---
110
167
 
111
168
  # Supported Frameworks
112
169
 
113
- - React
114
- - Next.js
115
- - Vue
116
- - Nuxt
117
- - Svelte
118
- - Astro
119
- - Node.js
120
- - Express
121
- - NestJS
170
+ Frontend:
171
+
172
+ - React
173
+ - Next.js
174
+ - Vue
175
+ - Nuxt
176
+ - Svelte
177
+ - Astro
178
+
179
+ Backend:
180
+
181
+ - Node.js
182
+ - Express
183
+ - NestJS
184
+ - Fastify
185
+ - Hono
186
+ - Bun
187
+ - Deno
188
+
189
+ ---
190
+
191
+ # How It Works
192
+
193
+ Eventra CLI:
194
+
195
+ 1. Scans your codebase
196
+ 2. Detects tracking calls
197
+ 3. Detects wrapper components
198
+ 4. Detects wrapper functions
199
+ 5. Syncs discovered events
200
+ 6. Registers events in Eventra
201
+
202
+ No runtime SDK required.
122
203
 
123
- ------------------------------------------------------------------------
204
+ ---
124
205
 
125
206
  # Requirements
126
207
 
127
- - Node.js 18+
128
- - JavaScript / TypeScript project
208
+ - Node.js 18+
209
+ - JavaScript / TypeScript project
129
210
 
130
- ------------------------------------------------------------------------
211
+ ---
131
212
 
132
213
  # License
133
214
 
@@ -27,8 +27,11 @@ async function init() {
27
27
  apiKey: answers.apiKey || "",
28
28
  events: [],
29
29
  wrappers: [],
30
+ functionWrappers: [],
30
31
  sync: {
31
- include: ["**/*.{ts,tsx,js,jsx}"],
32
+ include: [
33
+ "**/*.{ts,tsx,js,jsx,vue,svelte,astro}"
34
+ ],
32
35
  exclude: [
33
36
  "node_modules",
34
37
  "dist",
@@ -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 = "0.0.1";
12
+ const CLI_VERSION = package_json_1.default.version;
12
13
  async function send() {
13
- let config = await (0, config_1.loadConfig)();
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
- if (!config.events.length) {
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
- console.log(chalk_1.default.blue("Sending events..."));
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.status >= 400) {
54
- console.log(chalk_1.default.red(`Failed (${res.status})`));
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
  }
@@ -4,213 +4,54 @@ 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 inquirer_1 = __importDefault(require("inquirer"));
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
- let config = await (0, config_1.loadConfig)();
20
+ const config = await (0, config_1.loadConfig)();
14
21
  if (!config) {
15
- console.log(chalk_1.default.red("Run 'eventra init' first"));
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()
31
+ const functionWrappers = (config.functionWrappers ?? []).map((w) => ({
32
+ ...w,
33
+ path: w.path ?? "0"
34
+ }));
35
+ const componentWrappers = config.wrappers ?? [];
25
36
  for (const file of files) {
26
- const sourceFile = project.addSourceFileAtPath(file);
27
- const calls = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
28
- for (const call of calls) {
29
- const expression = call.getExpression();
30
- if (expression.getKind() ===
31
- ts_morph_1.SyntaxKind.PropertyAccessExpression) {
32
- const prop = expression.asKind(ts_morph_1.SyntaxKind.PropertyAccessExpression);
33
- if (!prop)
34
- continue;
35
- if (prop.getName() !== "track")
36
- continue;
37
- const args = call.getArguments();
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
- }
37
+ const parser = (0, router_1.detectParser)(file);
38
+ let content = await promises_1.default.readFile(file, "utf-8");
39
+ if (parser === "vue")
40
+ content = (0, vue_1.parseVue)(content);
41
+ if (parser === "svelte")
42
+ content = (0, svelte_1.parseSvelte)(content);
43
+ if (parser === "astro")
44
+ content = (0, astro_1.parseAstro)(content);
45
+ const virtualFile = parser === "ts"
46
+ ? file
47
+ : file + ".tsx";
48
+ const source = project.createSourceFile(virtualFile, content, { overwrite: true });
49
+ (0, track_1.scanTrack)(source).forEach((e) => events.add(e));
50
+ (0, function_wrappers_1.scanFunctionWrappers)(source, functionWrappers).forEach((e) => events.add(e));
51
+ (0, component_wrappers_1.scanComponentWrappers)(source, componentWrappers).forEach((e) => events.add(e));
107
52
  }
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
53
  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
54
  config.events = list;
214
55
  await (0, config_1.saveConfig)(config);
215
- console.log(chalk_1.default.green("eventra.json updated"));
56
+ console.log(chalk_1.default.green(`Found ${list.length} events`));
216
57
  }
package/dist/index.js CHANGED
File without changes
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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: ["**/*.{ts,tsx,js,jsx}"],
20
+ include: [
21
+ "**/*.{ts,tsx,js,jsx,vue,svelte,astro}"
22
+ ],
20
23
  exclude: [
21
24
  "node_modules",
22
25
  "dist",
@@ -0,0 +1,44 @@
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
+ node = unwrap(node);
11
+ for (let i = 1; i < parts.length; i++) {
12
+ if (!ts_morph_1.Node.isObjectLiteralExpression(node)) {
13
+ return null;
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() ===
31
+ ts_morph_1.SyntaxKind.NoSubstitutionTemplateLiteral) {
32
+ return node
33
+ .getText()
34
+ .replace(/`/g, "");
35
+ }
36
+ return null;
37
+ }
38
+ function unwrap(node) {
39
+ let current = node;
40
+ while (ts_morph_1.Node.isParenthesizedExpression(current)) {
41
+ current = current.getExpression();
42
+ }
43
+ return current;
44
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseAstro = parseAstro;
4
+ function parseAstro(content) {
5
+ return content;
6
+ }