@rayburst/cli 0.2.3 → 0.2.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.
|
@@ -309,10 +309,135 @@ function getUniqueNodeId(filePath, nodeName, gitHash, usedIds, idCounters) {
|
|
|
309
309
|
return id;
|
|
310
310
|
}
|
|
311
311
|
function isReactComponent(func) {
|
|
312
|
+
try {
|
|
313
|
+
let name = "";
|
|
314
|
+
if (typeof func.getName === "function") {
|
|
315
|
+
name = func.getName() || "";
|
|
316
|
+
}
|
|
317
|
+
if (!name && func.getParent) {
|
|
318
|
+
const parent = func.getParent();
|
|
319
|
+
if (parent && typeof parent.asKind === "function") {
|
|
320
|
+
const varDecl = parent.asKind(SyntaxKind.VariableDeclaration);
|
|
321
|
+
if (varDecl && typeof varDecl.getName === "function") {
|
|
322
|
+
name = varDecl.getName() || "";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const hasComponentName = name && /^[A-Z]/.test(name);
|
|
327
|
+
const returnType = func.getReturnType()?.getText() || "";
|
|
328
|
+
const hasJsxReturnType = returnType.includes("JSX.Element") || returnType.includes("React.ReactElement") || returnType.includes("ReactElement") || returnType.includes("React.ReactNode") || returnType.includes("ReactNode");
|
|
329
|
+
const body = func.getBody();
|
|
330
|
+
if (!body) return false;
|
|
331
|
+
const hasJsxElements = body.getDescendantsOfKind(SyntaxKind.JsxElement).length > 0 || body.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement).length > 0 || body.getDescendantsOfKind(SyntaxKind.JsxFragment).length > 0;
|
|
332
|
+
const hasHooks = body.getDescendantsOfKind(SyntaxKind.CallExpression).some((call) => {
|
|
333
|
+
const expr = call.getExpression().getText();
|
|
334
|
+
return expr.startsWith("use") && /^use[A-Z]/.test(expr);
|
|
335
|
+
});
|
|
336
|
+
if (hasJsxElements) return true;
|
|
337
|
+
if (hasJsxReturnType) return true;
|
|
338
|
+
if (hasComponentName && hasHooks) return true;
|
|
339
|
+
return false;
|
|
340
|
+
} catch (error) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
function analyzeReturnStatements(func) {
|
|
312
345
|
const body = func.getBody();
|
|
313
|
-
if (!body)
|
|
314
|
-
|
|
315
|
-
|
|
346
|
+
if (!body) {
|
|
347
|
+
return {
|
|
348
|
+
hasJsxReturn: false,
|
|
349
|
+
hasNullReturn: false,
|
|
350
|
+
hasUndefinedReturn: false,
|
|
351
|
+
returnValueSummary: "void",
|
|
352
|
+
primaryReturnType: "undefined"
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const returnStatements = body.getDescendantsOfKind(SyntaxKind.ReturnStatement);
|
|
356
|
+
let hasJsxReturn = false;
|
|
357
|
+
let hasNullReturn = false;
|
|
358
|
+
let hasUndefinedReturn = false;
|
|
359
|
+
const returnTypes = [];
|
|
360
|
+
for (const returnStmt of returnStatements) {
|
|
361
|
+
const expr = returnStmt.getExpression();
|
|
362
|
+
if (!expr) {
|
|
363
|
+
hasUndefinedReturn = true;
|
|
364
|
+
returnTypes.push("undefined");
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (Node.isJsxElement(expr) || Node.isJsxSelfClosingElement(expr) || Node.isJsxFragment(expr)) {
|
|
368
|
+
hasJsxReturn = true;
|
|
369
|
+
let jsxName = "JSX";
|
|
370
|
+
if (Node.isJsxElement(expr)) {
|
|
371
|
+
jsxName = expr.getOpeningElement().getTagNameNode().getText();
|
|
372
|
+
} else if (Node.isJsxSelfClosingElement(expr)) {
|
|
373
|
+
jsxName = expr.getTagNameNode().getText();
|
|
374
|
+
} else {
|
|
375
|
+
jsxName = "<>";
|
|
376
|
+
}
|
|
377
|
+
returnTypes.push(`<${jsxName}>`);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (expr.getKind() === SyntaxKind.NullKeyword) {
|
|
381
|
+
hasNullReturn = true;
|
|
382
|
+
returnTypes.push("null");
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
if (expr.getKind() === SyntaxKind.Identifier && expr.getText() === "undefined") {
|
|
386
|
+
hasUndefinedReturn = true;
|
|
387
|
+
returnTypes.push("undefined");
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (Node.isConditionalExpression(expr)) {
|
|
391
|
+
const whenTrue = expr.getWhenTrue();
|
|
392
|
+
const whenFalse = expr.getWhenFalse();
|
|
393
|
+
const trueIsJsx = Node.isJsxElement(whenTrue) || Node.isJsxSelfClosingElement(whenTrue);
|
|
394
|
+
const falseIsJsx = Node.isJsxElement(whenFalse) || Node.isJsxSelfClosingElement(whenFalse);
|
|
395
|
+
if (trueIsJsx || falseIsJsx) hasJsxReturn = true;
|
|
396
|
+
if (whenTrue.getText() === "null") hasNullReturn = true;
|
|
397
|
+
if (whenFalse.getText() === "null") hasNullReturn = true;
|
|
398
|
+
const trueText = whenTrue.getText().length > 20 ? whenTrue.getText().substring(0, 17) + "..." : whenTrue.getText();
|
|
399
|
+
const falseText = whenFalse.getText().length > 20 ? whenFalse.getText().substring(0, 17) + "..." : whenFalse.getText();
|
|
400
|
+
returnTypes.push(`${trueText} : ${falseText}`);
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
const exprText = expr.getText();
|
|
404
|
+
const truncated = exprText.length > 50 ? exprText.substring(0, 47) + "..." : exprText;
|
|
405
|
+
returnTypes.push(truncated);
|
|
406
|
+
}
|
|
407
|
+
let primaryReturnType = "mixed";
|
|
408
|
+
if (hasJsxReturn && !hasNullReturn && !hasUndefinedReturn) {
|
|
409
|
+
primaryReturnType = "jsx";
|
|
410
|
+
} else if (hasNullReturn && !hasJsxReturn && !hasUndefinedReturn) {
|
|
411
|
+
primaryReturnType = "null";
|
|
412
|
+
} else if (hasUndefinedReturn && !hasJsxReturn && !hasNullReturn) {
|
|
413
|
+
primaryReturnType = "undefined";
|
|
414
|
+
} else if (returnTypes.length === 1) {
|
|
415
|
+
primaryReturnType = "primitive";
|
|
416
|
+
}
|
|
417
|
+
const uniqueReturns = Array.from(new Set(returnTypes));
|
|
418
|
+
const returnValueSummary = uniqueReturns.join(" | ") || "void";
|
|
419
|
+
return {
|
|
420
|
+
hasJsxReturn,
|
|
421
|
+
hasNullReturn,
|
|
422
|
+
hasUndefinedReturn,
|
|
423
|
+
returnValueSummary,
|
|
424
|
+
primaryReturnType
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function getReturnDescription(returnAnalysis) {
|
|
428
|
+
if (returnAnalysis.hasJsxReturn && returnAnalysis.hasNullReturn) {
|
|
429
|
+
return "Returns JSX or null";
|
|
430
|
+
}
|
|
431
|
+
if (returnAnalysis.hasJsxReturn) {
|
|
432
|
+
return "Returns JSX";
|
|
433
|
+
}
|
|
434
|
+
if (returnAnalysis.hasNullReturn) {
|
|
435
|
+
return "Returns null";
|
|
436
|
+
}
|
|
437
|
+
if (returnAnalysis.hasUndefinedReturn) {
|
|
438
|
+
return "Returns void";
|
|
439
|
+
}
|
|
440
|
+
return "Returns value";
|
|
316
441
|
}
|
|
317
442
|
function extractComponents(sourceFile, relativePath, gitHash, baseX, startY, nodes, nodeMap, usedIds, idCounters) {
|
|
318
443
|
let count = 0;
|
|
@@ -325,6 +450,7 @@ function extractComponents(sourceFile, relativePath, gitHash, baseX, startY, nod
|
|
|
325
450
|
const params = func.getParameters();
|
|
326
451
|
const propsParam = params[0];
|
|
327
452
|
const propsType = propsParam ? propsParam.getType().getText() : "any";
|
|
453
|
+
const returnAnalysis = analyzeReturnStatements(func);
|
|
328
454
|
const node = {
|
|
329
455
|
id,
|
|
330
456
|
type: "component",
|
|
@@ -333,7 +459,12 @@ function extractComponents(sourceFile, relativePath, gitHash, baseX, startY, nod
|
|
|
333
459
|
componentName: name,
|
|
334
460
|
props: propsType,
|
|
335
461
|
label: name,
|
|
336
|
-
description: `Component in ${relativePath}
|
|
462
|
+
description: `Component in ${relativePath}`,
|
|
463
|
+
returnValueSummary: returnAnalysis.returnValueSummary,
|
|
464
|
+
returnDescription: getReturnDescription(returnAnalysis),
|
|
465
|
+
hasJsxReturn: returnAnalysis.hasJsxReturn,
|
|
466
|
+
hasNullReturn: returnAnalysis.hasNullReturn,
|
|
467
|
+
primaryReturnType: returnAnalysis.primaryReturnType
|
|
337
468
|
}
|
|
338
469
|
};
|
|
339
470
|
nodes.push(node);
|
|
@@ -353,6 +484,7 @@ function extractComponents(sourceFile, relativePath, gitHash, baseX, startY, nod
|
|
|
353
484
|
const params = init.getParameters();
|
|
354
485
|
const propsParam = params[0];
|
|
355
486
|
const propsType = propsParam ? propsParam.getType().getText() : "any";
|
|
487
|
+
const returnAnalysis = analyzeReturnStatements(init);
|
|
356
488
|
const node = {
|
|
357
489
|
id,
|
|
358
490
|
type: "component",
|
|
@@ -361,7 +493,12 @@ function extractComponents(sourceFile, relativePath, gitHash, baseX, startY, nod
|
|
|
361
493
|
componentName: name,
|
|
362
494
|
props: propsType,
|
|
363
495
|
label: name,
|
|
364
|
-
description: `Component in ${relativePath}
|
|
496
|
+
description: `Component in ${relativePath}`,
|
|
497
|
+
returnValueSummary: returnAnalysis.returnValueSummary,
|
|
498
|
+
returnDescription: getReturnDescription(returnAnalysis),
|
|
499
|
+
hasJsxReturn: returnAnalysis.hasJsxReturn,
|
|
500
|
+
hasNullReturn: returnAnalysis.hasNullReturn,
|
|
501
|
+
primaryReturnType: returnAnalysis.primaryReturnType
|
|
365
502
|
}
|
|
366
503
|
};
|
|
367
504
|
nodes.push(node);
|
|
@@ -389,6 +526,7 @@ function extractFunctions(sourceFile, relativePath, gitHash, baseX, startY, node
|
|
|
389
526
|
return `${paramName}: ${paramType}`;
|
|
390
527
|
}).join(", ");
|
|
391
528
|
const returnType = func.getReturnType().getText();
|
|
529
|
+
const returnAnalysis = analyzeReturnStatements(func);
|
|
392
530
|
const node = {
|
|
393
531
|
id,
|
|
394
532
|
type: "function",
|
|
@@ -398,7 +536,12 @@ function extractFunctions(sourceFile, relativePath, gitHash, baseX, startY, node
|
|
|
398
536
|
parameters: params,
|
|
399
537
|
returnType,
|
|
400
538
|
label: name,
|
|
401
|
-
description: `Function in ${relativePath}
|
|
539
|
+
description: `Function in ${relativePath}`,
|
|
540
|
+
returnValueSummary: returnAnalysis.returnValueSummary,
|
|
541
|
+
returnDescription: getReturnDescription(returnAnalysis),
|
|
542
|
+
hasJsxReturn: returnAnalysis.hasJsxReturn,
|
|
543
|
+
hasNullReturn: returnAnalysis.hasNullReturn,
|
|
544
|
+
primaryReturnType: returnAnalysis.primaryReturnType
|
|
402
545
|
}
|
|
403
546
|
};
|
|
404
547
|
nodes.push(node);
|
package/dist/index.js
CHANGED
package/dist/vite-plugin.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rayburst/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Rayburst - Automatic code analysis for TypeScript/JavaScript projects via Vite plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@rayburst/types": "^0.1.3",
|
|
46
45
|
"chalk": "^5.3.0",
|
|
47
46
|
"ts-morph": "^21.0.1",
|
|
48
47
|
"zod": "^4.2.0"
|
|
49
48
|
},
|
|
50
49
|
"devDependencies": {
|
|
50
|
+
"@rayburst/types": "^0.1.4",
|
|
51
51
|
"@types/node": "^25.0.2",
|
|
52
52
|
"tsup": "^8.5.1",
|
|
53
53
|
"typescript": "^5.9.3",
|