@builder.io/mitosis
Version:
Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io
100 lines (99 loc) • 3.86 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.findSignals = void 0;
const ts_morph_1 = require("ts-morph");
const typescript_project_1 = require("../../helpers/typescript-project");
const MITOSIS_IMPORT_PATHS = [
// actual production path
'/node_modules/@builder.io/mitosis/',
// possible path if symlinking mitosis locally
'/mitosis/packages/core/',
];
const findSignals = ({ filePath, project }) => {
const ast = project.getSourceFileOrThrow(filePath);
if (ast === undefined) {
throw new Error('Could not find AST. Please provide a correct `filePath`.');
}
const reactiveValues = {
props: new Set(),
state: new Set(),
context: new Set(),
};
const propsSymbol = (0, typescript_project_1.getPropsSymbol)(ast);
const contextSymbols = (0, typescript_project_1.getContextSymbols)(ast);
const checkIsSignalSymbol = (type) => {
var _a;
const symbol = (_a = type.getTargetType()) === null || _a === void 0 ? void 0 : _a.getAliasSymbol();
if (!symbol || symbol.getName() !== 'Signal')
return false;
const compilerSymbol = symbol === null || symbol === void 0 ? void 0 : symbol.compilerSymbol;
const parent = compilerSymbol.parent;
if (!parent)
return false;
if (MITOSIS_IMPORT_PATHS.some((path) => parent.getName().includes(path))) {
return true;
}
return false;
};
const checkIsOptionalSignal = (node) => {
let hasUndefined = false;
let hasSignal = false;
const perfectMatch = node
.getType()
.getUnionTypes()
.every((type) => {
if (type.isUndefined()) {
hasUndefined = true;
return true;
}
else if (checkIsSignalSymbol(type)) {
hasSignal = true;
return true;
}
return false;
});
return perfectMatch && hasUndefined && hasSignal;
};
ast.forEachDescendant((parentNode) => {
if (ts_morph_1.Node.isPropertyAccessExpression(parentNode)) {
const node = parentNode.getExpression();
const isOptionalAccess = parentNode.hasQuestionDotToken();
const isSignal = isOptionalAccess
? checkIsOptionalSignal(node)
: checkIsSignalSymbol(node.getType());
if (!isSignal)
return;
let isInsideType = false;
let isInsideDeclaration = false;
node.getParentWhile((parent, child) => {
// stop once we hit the function block
if (ts_morph_1.Node.isBlock(child) || ts_morph_1.Node.isBlock(parent)) {
return false;
}
// crawl up parents to make sure we're not inside a type
if (ts_morph_1.Node.isTypeNode(parent) || ts_morph_1.Node.isTypeAliasDeclaration(parent)) {
isInsideType = true;
return false;
}
return true;
});
if (isInsideType)
return;
if (isInsideDeclaration)
return;
const nodeSymbol = node.getSymbol();
if (ts_morph_1.Node.isPropertyAccessExpression(node) &&
node.getExpression().getSymbol() === propsSymbol) {
reactiveValues.props.add(node.getNameNode().getText());
}
else if (nodeSymbol && contextSymbols.has(nodeSymbol)) {
reactiveValues.context.add(node.getText());
}
else {
reactiveValues.state.add(node.getText());
}
}
});
return reactiveValues;
};
exports.findSignals = findSignals;
;