@eventra_dev/eventra-cli 0.1.1 → 0.1.3

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 (45) hide show
  1. package/README.md +48 -73
  2. package/dist/commands/check.js +18 -7
  3. package/dist/commands/send.js +7 -1
  4. package/dist/commands/sync.js +5 -3
  5. package/dist/commands/watch.js +13 -55
  6. package/dist/engine/callResolver.js +15 -24
  7. package/dist/engine/engine.js +32 -7
  8. package/dist/engine/graph.js +50 -9
  9. package/dist/engine/hash.js +10 -0
  10. package/dist/engine/languageService.js +74 -0
  11. package/dist/engine/resolver.js +88 -24
  12. package/dist/engine/scanner.js +57 -67
  13. package/dist/utils/config.js +7 -2
  14. package/dist/utils/parsers/astro.js +8 -1
  15. package/dist/utils/parsers/router.js +1 -0
  16. package/dist/utils/parsers/svelte.js +4 -1
  17. package/dist/utils/parsers/vue.js +13 -4
  18. package/dist/utils/processFile.js +3 -1
  19. package/package.json +1 -1
  20. package/src/commands/check.ts +21 -7
  21. package/src/commands/send.ts +8 -2
  22. package/src/commands/sync.ts +6 -3
  23. package/src/commands/watch.ts +14 -60
  24. package/src/engine/callResolver.ts +21 -32
  25. package/src/engine/engine.ts +40 -7
  26. package/src/engine/graph.ts +58 -11
  27. package/src/engine/hash.ts +5 -0
  28. package/src/engine/languageService.ts +103 -0
  29. package/src/engine/resolver.ts +104 -24
  30. package/src/engine/scanner.ts +67 -74
  31. package/src/types.ts +5 -0
  32. package/src/utils/config.ts +15 -33
  33. package/src/utils/parsers/astro.ts +11 -4
  34. package/src/utils/parsers/router.ts +5 -10
  35. package/src/utils/parsers/svelte.ts +6 -4
  36. package/src/utils/parsers/vue.ts +15 -5
  37. package/src/utils/processFile.ts +6 -3
  38. package/dist/engine/extract.js +0 -53
  39. package/dist/engine/flow.js +0 -38
  40. package/dist/engine/project.js +0 -74
  41. package/dist/engine/symbol.js +0 -31
  42. package/src/engine/extract.ts +0 -74
  43. package/src/engine/flow.ts +0 -54
  44. package/src/engine/project.ts +0 -75
  45. package/src/engine/symbol.ts +0 -42
@@ -1,5 +1,7 @@
1
- export function parseSvelte(
2
- content: string
3
- ) {
4
- return content;
1
+ export function parseSvelte(content: string) {
2
+ const scriptMatches = [
3
+ ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
4
+ ];
5
+
6
+ return scriptMatches.map(m => m[1]).join("\n");
5
7
  }
@@ -1,16 +1,26 @@
1
1
  export function parseVue(content: string) {
2
- const scriptMatch = content.match(/<script[\s\S]*?>([\s\S]*?)<\/script>/);
3
- const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/);
2
+ const scriptMatches = [
3
+ ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
4
+ ];
5
+
6
+ const script = scriptMatches.map(m => m[1]).join("\n");
4
7
 
5
- const script = scriptMatch?.[1] ?? "";
8
+ // template
9
+ const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/);
6
10
  let template = templateMatch?.[1] ?? "";
7
11
 
8
12
  template = template.replace(/<!--[\s\S]*?-->/g, "");
9
13
 
14
+ // Vue → JSX
10
15
  template = template
16
+ .replace(/\bclass=/g, "className=")
17
+ .replace(/\bfor=/g, "htmlFor=")
18
+ .replace(/@(\w+)=/g, (_, e) => {
19
+ const name = e.charAt(0).toUpperCase() + e.slice(1);
20
+ return `on${name}=`;
21
+ })
11
22
  .replace(/v-if="[^"]+"/g, "")
12
- .replace(/v-for="[^"]+"/g, "")
13
- .replace(/@click=/g, "onClick=");
23
+ .replace(/v-for="[^"]+"/g, "");
14
24
 
15
25
  const jsx = `
16
26
  const __VUE_JSX__ = (
@@ -10,9 +10,12 @@ export function processFile(file: string, content: string) {
10
10
  if (parser === "svelte") content = parseSvelte(content);
11
11
  if (parser === "astro") content = parseAstro(content);
12
12
 
13
- const virtualFile = file.endsWith(".vue")
14
- ? file + ".tsx"
15
- : file;
13
+ const virtualFile =
14
+ file.endsWith(".vue") ||
15
+ file.endsWith(".svelte") ||
16
+ file.endsWith(".astro")
17
+ ? file + ".tsx"
18
+ : file;
16
19
 
17
20
  return { content, virtualFile };
18
21
  }
@@ -1,53 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.extractEventsFromArgs = extractEventsFromArgs;
4
- const ts_morph_1 = require("ts-morph");
5
- const resolver_1 = require("./resolver");
6
- function extractEventsFromArgs(args, checker) {
7
- return args.flatMap(arg => extract(arg, checker));
8
- }
9
- function extract(node, checker) {
10
- if (ts_morph_1.Node.isStringLiteral(node)) {
11
- return [{ value: node.getLiteralText(), dynamic: false }];
12
- }
13
- if (ts_morph_1.Node.isNoSubstitutionTemplateLiteral(node)) {
14
- return [{ value: node.getLiteralText(), dynamic: false }];
15
- }
16
- if (ts_morph_1.Node.isTemplateExpression(node)) {
17
- let result = node.getHead().getLiteralText();
18
- for (const span of node.getTemplateSpans()) {
19
- result += "*";
20
- result += span.getLiteral().getLiteralText();
21
- }
22
- return [{ value: result, dynamic: true }];
23
- }
24
- if (ts_morph_1.Node.isObjectLiteralExpression(node)) {
25
- return extractObject(node, checker);
26
- }
27
- const resolved = (0, resolver_1.resolveNodeValue)(node, checker);
28
- if (resolved) {
29
- return resolved.values.map(v => ({
30
- value: v,
31
- dynamic: resolved.dynamic,
32
- }));
33
- }
34
- return [];
35
- }
36
- function extractObject(obj, checker) {
37
- const res = [];
38
- for (const prop of obj.getProperties()) {
39
- if (!ts_morph_1.Node.isPropertyAssignment(prop))
40
- continue;
41
- const name = prop.getName();
42
- const init = prop.getInitializer();
43
- if (!init)
44
- continue;
45
- if (["event", "name", "action", "type"].includes(name)) {
46
- res.push(...extract(init, checker));
47
- }
48
- if (ts_morph_1.Node.isObjectLiteralExpression(init)) {
49
- res.push(...extractObject(init, checker));
50
- }
51
- }
52
- return res;
53
- }
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getForwardedParamIndex = getForwardedParamIndex;
4
- const ts_morph_1 = require("ts-morph");
5
- function getBodyNodes(fn) {
6
- const body = fn.getBody();
7
- if (!body)
8
- return [];
9
- if (ts_morph_1.Node.isBlock(body))
10
- return body.getStatements();
11
- return [body];
12
- }
13
- function getForwardedParamIndex(fn) {
14
- if (!ts_morph_1.Node.isFunctionDeclaration(fn) &&
15
- !ts_morph_1.Node.isArrowFunction(fn) &&
16
- !ts_morph_1.Node.isFunctionExpression(fn))
17
- return null;
18
- const f = fn;
19
- const params = f.getParameters();
20
- for (const node of getBodyNodes(f)) {
21
- const calls = node.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
22
- for (const call of calls) {
23
- const name = call.getExpression().getText();
24
- if (!/(track|event|log|analytics|capture|send)/i.test(name))
25
- continue;
26
- const args = call.getArguments();
27
- for (let i = 0; i < args.length; i++) {
28
- const arg = args[i];
29
- if (ts_morph_1.Node.isIdentifier(arg)) {
30
- const idx = params.findIndex(p => p.getName() === arg.getText());
31
- if (idx !== -1)
32
- return idx;
33
- }
34
- }
35
- }
36
- }
37
- return null;
38
- }
@@ -1,74 +0,0 @@
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.ProjectGraph = void 0;
7
- const ts_morph_1 = require("ts-morph");
8
- const path_1 = __importDefault(require("path"));
9
- const fs_1 = __importDefault(require("fs"));
10
- function normalize(file) {
11
- return path_1.default.resolve(file);
12
- }
13
- function findTsConfig(start) {
14
- let dir = path_1.default.dirname(start);
15
- while (true) {
16
- const file = path_1.default.join(dir, "tsconfig.json");
17
- if (fs_1.default.existsSync(file))
18
- return file;
19
- const parent = path_1.default.dirname(dir);
20
- if (parent === dir)
21
- break;
22
- dir = parent;
23
- }
24
- return null;
25
- }
26
- function getScriptKind(file) {
27
- if (file.endsWith(".tsx"))
28
- return ts_morph_1.ts.ScriptKind.TSX;
29
- if (file.endsWith(".jsx"))
30
- return ts_morph_1.ts.ScriptKind.JSX;
31
- if (file.endsWith(".js"))
32
- return ts_morph_1.ts.ScriptKind.JS;
33
- if (file.endsWith(".vue"))
34
- return ts_morph_1.ts.ScriptKind.TSX;
35
- return ts_morph_1.ts.ScriptKind.TS;
36
- }
37
- class ProjectGraph {
38
- project;
39
- constructor(entry) {
40
- const tsconfig = findTsConfig(entry);
41
- this.project = tsconfig
42
- ? new ts_morph_1.Project({
43
- tsConfigFilePath: tsconfig,
44
- skipAddingFilesFromTsConfig: false,
45
- })
46
- : new ts_morph_1.Project({
47
- useInMemoryFileSystem: true,
48
- compilerOptions: {
49
- allowJs: true,
50
- jsx: ts_morph_1.ts.JsxEmit.Preserve,
51
- moduleResolution: ts_morph_1.ts.ModuleResolutionKind.NodeJs,
52
- target: ts_morph_1.ts.ScriptTarget.ESNext,
53
- },
54
- });
55
- }
56
- getSource(file, content) {
57
- const filePath = normalize(file);
58
- let source = this.project.getSourceFile(filePath);
59
- if (!source) {
60
- source = this.project.createSourceFile(filePath, content, {
61
- overwrite: true,
62
- scriptKind: getScriptKind(filePath),
63
- });
64
- }
65
- else {
66
- source.replaceWithText(content);
67
- }
68
- return source;
69
- }
70
- getChecker() {
71
- return this.project.getTypeChecker().compilerObject;
72
- }
73
- }
74
- exports.ProjectGraph = ProjectGraph;
@@ -1,31 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveNodeValue = resolveNodeValue;
4
- const ts_morph_1 = require("ts-morph");
5
- function resolveNodeValue(node, checker) {
6
- if (ts_morph_1.Node.isIdentifier(node)) {
7
- const symbol = checker.getSymbolAtLocation(node.compilerNode);
8
- if (!symbol)
9
- return null;
10
- const decls = symbol.getDeclarations() ?? [];
11
- for (const d of decls) {
12
- if (ts_morph_1.ts.isVariableDeclaration(d) && d.initializer) {
13
- if (ts_morph_1.Node.isStringLiteral(d.initializer)) {
14
- return {
15
- values: [d.initializer.text],
16
- dynamic: false
17
- };
18
- }
19
- }
20
- if (ts_morph_1.ts.isParameter(d) && d.initializer) {
21
- if (ts_morph_1.Node.isStringLiteral(d.initializer)) {
22
- return {
23
- values: [d.initializer.text],
24
- dynamic: false
25
- };
26
- }
27
- }
28
- }
29
- }
30
- return null;
31
- }
@@ -1,74 +0,0 @@
1
- import { Node, ObjectLiteralExpression, ts } from "ts-morph";
2
- import { resolveNodeValue } from "./resolver";
3
-
4
- export type Extracted = {
5
- value: string;
6
- dynamic: boolean;
7
- };
8
-
9
- export function extractEventsFromArgs(
10
- args: Node[],
11
- checker: ts.TypeChecker
12
- ): Extracted[] {
13
- return args.flatMap(arg => extract(arg, checker));
14
- }
15
-
16
- function extract(node: Node, checker: ts.TypeChecker): Extracted[] {
17
- if (Node.isStringLiteral(node)) {
18
- return [{ value: node.getLiteralText(), dynamic: false }];
19
- }
20
-
21
- if (Node.isNoSubstitutionTemplateLiteral(node)) {
22
- return [{ value: node.getLiteralText(), dynamic: false }];
23
- }
24
-
25
- if (Node.isTemplateExpression(node)) {
26
- let result = node.getHead().getLiteralText();
27
-
28
- for (const span of node.getTemplateSpans()) {
29
- result += "*";
30
- result += span.getLiteral().getLiteralText();
31
- }
32
-
33
- return [{ value: result, dynamic: true }];
34
- }
35
-
36
- if (Node.isObjectLiteralExpression(node)) {
37
- return extractObject(node, checker);
38
- }
39
-
40
- const resolved = resolveNodeValue(node, checker);
41
- if (resolved) {
42
- return resolved.values.map(v => ({
43
- value: v,
44
- dynamic: resolved.dynamic,
45
- }));
46
- }
47
-
48
- return [];
49
- }
50
-
51
- function extractObject(
52
- obj: ObjectLiteralExpression,
53
- checker: ts.TypeChecker
54
- ): Extracted[] {
55
- const res: Extracted[] = [];
56
-
57
- for (const prop of obj.getProperties()) {
58
- if (!Node.isPropertyAssignment(prop)) continue;
59
-
60
- const name = prop.getName();
61
- const init = prop.getInitializer();
62
- if (!init) continue;
63
-
64
- if (["event", "name", "action", "type"].includes(name)) {
65
- res.push(...extract(init, checker));
66
- }
67
-
68
- if (Node.isObjectLiteralExpression(init)) {
69
- res.push(...extractObject(init, checker));
70
- }
71
- }
72
-
73
- return res;
74
- }
@@ -1,54 +0,0 @@
1
- import {
2
- Node,
3
- SyntaxKind,
4
- FunctionDeclaration,
5
- ArrowFunction,
6
- FunctionExpression
7
- } from "ts-morph";
8
-
9
- type Fn =
10
- | FunctionDeclaration
11
- | ArrowFunction
12
- | FunctionExpression;
13
-
14
- function getBodyNodes(fn: Fn) {
15
- const body = fn.getBody();
16
- if (!body) return [];
17
-
18
- if (Node.isBlock(body)) return body.getStatements();
19
- return [body];
20
- }
21
-
22
- export function getForwardedParamIndex(fn: Node): number | null {
23
- if (
24
- !Node.isFunctionDeclaration(fn) &&
25
- !Node.isArrowFunction(fn) &&
26
- !Node.isFunctionExpression(fn)
27
- ) return null;
28
-
29
- const f = fn as Fn;
30
- const params = f.getParameters();
31
-
32
- for (const node of getBodyNodes(f)) {
33
- const calls = node.getDescendantsOfKind(SyntaxKind.CallExpression);
34
-
35
- for (const call of calls) {
36
- const name = call.getExpression().getText();
37
-
38
- if (!/(track|event|log|analytics|capture|send)/i.test(name)) continue;
39
-
40
- const args = call.getArguments();
41
-
42
- for (let i = 0; i < args.length; i++) {
43
- const arg = args[i];
44
-
45
- if (Node.isIdentifier(arg)) {
46
- const idx = params.findIndex(p => p.getName() === arg.getText());
47
- if (idx !== -1) return idx;
48
- }
49
- }
50
- }
51
- }
52
-
53
- return null;
54
- }
@@ -1,75 +0,0 @@
1
- import { Project, SourceFile, ts } from "ts-morph";
2
- import path from "path";
3
- import fs from "fs";
4
-
5
- function normalize(file: string) {
6
- return path.resolve(file);
7
- }
8
-
9
- function findTsConfig(start: string): string | null {
10
- let dir = path.dirname(start);
11
-
12
- while (true) {
13
- const file = path.join(dir, "tsconfig.json");
14
- if (fs.existsSync(file)) return file;
15
-
16
- const parent = path.dirname(dir);
17
- if (parent === dir) break;
18
-
19
- dir = parent;
20
- }
21
-
22
- return null;
23
- }
24
-
25
- function getScriptKind(file: string): ts.ScriptKind {
26
- if (file.endsWith(".tsx")) return ts.ScriptKind.TSX;
27
- if (file.endsWith(".jsx")) return ts.ScriptKind.JSX;
28
- if (file.endsWith(".js")) return ts.ScriptKind.JS;
29
- if (file.endsWith(".vue")) return ts.ScriptKind.TSX;
30
- return ts.ScriptKind.TS;
31
- }
32
-
33
- export class ProjectGraph {
34
- private project: Project;
35
-
36
- constructor(entry: string) {
37
- const tsconfig = findTsConfig(entry);
38
-
39
- this.project = tsconfig
40
- ? new Project({
41
- tsConfigFilePath: tsconfig,
42
- skipAddingFilesFromTsConfig: false,
43
- })
44
- : new Project({
45
- useInMemoryFileSystem: true,
46
- compilerOptions: {
47
- allowJs: true,
48
- jsx: ts.JsxEmit.Preserve,
49
- moduleResolution: ts.ModuleResolutionKind.NodeJs,
50
- target: ts.ScriptTarget.ESNext,
51
- },
52
- });
53
- }
54
-
55
- getSource(file: string, content: string): SourceFile {
56
- const filePath = normalize(file);
57
-
58
- let source = this.project.getSourceFile(filePath);
59
-
60
- if (!source) {
61
- source = this.project.createSourceFile(filePath, content, {
62
- overwrite: true,
63
- scriptKind: getScriptKind(filePath),
64
- });
65
- } else {
66
- source.replaceWithText(content);
67
- }
68
-
69
- return source;
70
- }
71
-
72
- getChecker() {
73
- return this.project.getTypeChecker().compilerObject;
74
- }
75
- }
@@ -1,42 +0,0 @@
1
- import { Node, ts } from "ts-morph";
2
-
3
- export type ResolveResult = {
4
- values: string[];
5
- dynamic: boolean;
6
- };
7
-
8
- export function resolveNodeValue(
9
- node: Node,
10
- checker: ts.TypeChecker
11
- ): ResolveResult | null {
12
-
13
- if (Node.isIdentifier(node)) {
14
- const symbol = checker.getSymbolAtLocation(node.compilerNode);
15
- if (!symbol) return null;
16
-
17
- const decls = symbol.getDeclarations() ?? [];
18
-
19
- for (const d of decls) {
20
-
21
- if (ts.isVariableDeclaration(d) && d.initializer) {
22
- if (Node.isStringLiteral(d.initializer as any)) {
23
- return {
24
- values: [(d.initializer as any).text],
25
- dynamic: false
26
- };
27
- }
28
- }
29
-
30
- if (ts.isParameter(d) && d.initializer) {
31
- if (Node.isStringLiteral(d.initializer as any)) {
32
- return {
33
- values: [(d.initializer as any).text],
34
- dynamic: false
35
- };
36
- }
37
- }
38
- }
39
- }
40
-
41
- return null;
42
- }