UNPKG

sicua

Version:

A tool for analyzing project structure and dependencies

225 lines (224 loc) 8.81 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StoreAnalysisUtils = void 0; const typescript_1 = __importDefault(require("typescript")); class StoreAnalysisUtils { /** * Detects store initialization patterns across different libraries */ static detectStoreInitialization(node) { // Check function name for common patterns const functionName = this.getStoreFunctionName(node); if (!functionName) return { type: null, name: null, initializerNode: null }; // Redux patterns if (functionName === "configureStore" || functionName === "createStore" || functionName === "legacy_createStore") { return { type: "redux", name: this.getStoreDeclarationName(node) || "store", initializerNode: node.arguments[0], }; } // Zustand patterns if (functionName === "create" || functionName === "createStore") { return { type: "zustand", name: this.getStoreDeclarationName(node) || "zustandStore", initializerNode: node.arguments[0], }; } // Jotai patterns if (functionName === "atom" || functionName === "atomWithStorage") { return { type: "jotai", name: this.getStoreDeclarationName(node) || "atom", initializerNode: node.arguments[0], }; } // Recoil patterns if (functionName === "atom" || functionName === "atomFamily" || functionName === "selector" || functionName === "selectorFamily") { return { type: "recoil", name: this.getStoreDeclarationName(node) || "recoilState", initializerNode: node.arguments[0], }; } return { type: null, name: null, initializerNode: null }; } /** * Analyzes hook usage patterns across different state management libraries */ static analyzeHookUsage(node) { const hookName = this.getHookName(node); if (!hookName) return { type: null, hookType: null, accessor: null }; // Redux hooks if (hookName === "useSelector") { return { type: "read", hookType: "redux", accessor: node.arguments[0] }; } if (hookName === "useDispatch") { return { type: "write", hookType: "redux", accessor: null }; } // Zustand hooks (useStore) if (this.isZustandHook(hookName)) { return { type: "both", hookType: "zustand", accessor: node.arguments[0], }; } // Recoil hooks if (hookName === "useRecoilValue") { return { type: "read", hookType: "recoil", accessor: node.arguments[0] }; } if (hookName === "useSetRecoilState") { return { type: "write", hookType: "recoil", accessor: node.arguments[0] }; } if (hookName === "useRecoilState") { return { type: "both", hookType: "recoil", accessor: node.arguments[0] }; } // Jotai hooks if (hookName === "useAtomValue") { return { type: "read", hookType: "jotai", accessor: node.arguments[0] }; } if (hookName === "useSetAtom") { return { type: "write", hookType: "jotai", accessor: node.arguments[0] }; } if (hookName === "useAtom") { return { type: "both", hookType: "jotai", accessor: node.arguments[0] }; } return { type: null, hookType: null, accessor: null }; } /** * Analyzes state update patterns across different libraries */ static analyzeStateUpdate(node) { // Direct assignment if (typescript_1.default.isObjectLiteralExpression(node)) { return { type: "direct", updatePattern: node.getText(), affectedProperties: this.extractAffectedProperties(node), }; } // Functional update if (typescript_1.default.isArrowFunction(node) || typescript_1.default.isFunctionExpression(node)) { return { type: "functional", updatePattern: this.extractUpdatePattern(node), affectedProperties: this.findModifiedProperties(node), }; } // Action-based update (Redux-style) if (typescript_1.default.isCallExpression(node) && this.isActionDispatch(node)) { return { type: "action", updatePattern: this.extractActionPattern(node), affectedProperties: this.findActionAffectedProperties(node), }; } return { type: null, updatePattern: null, affectedProperties: [] }; } /** * Determines if a hook follows common store hook naming patterns */ static isStoreHook(hookName, storeName) { const normalizedHookName = hookName.toLowerCase(); const normalizedStoreName = storeName.toLowerCase(); return (normalizedHookName === `use${normalizedStoreName}` || normalizedHookName === `use${normalizedStoreName}store` || normalizedHookName === normalizedStoreName || normalizedHookName.startsWith("use") && normalizedHookName.includes(normalizedStoreName.replace("store", ""))); } // Private helper methods static getStoreFunctionName(node) { if (typescript_1.default.isIdentifier(node.expression)) { return node.expression.text; } if (typescript_1.default.isPropertyAccessExpression(node.expression) && typescript_1.default.isIdentifier(node.expression.name)) { return node.expression.name.text; } return null; } static getStoreDeclarationName(node) { if (node.parent && typescript_1.default.isVariableDeclaration(node.parent)) { return node.parent.name.getText(); } return null; } static getHookName(node) { return typescript_1.default.isIdentifier(node.expression) ? node.expression.text : null; } static isZustandHook(hookName) { return /^use[A-Z].*Store$/.test(hookName) || /^use[A-Z].*$/.test(hookName); } static extractAffectedProperties(node) { return node.properties .filter(typescript_1.default.isPropertyAssignment) .map((prop) => prop.name.getText()); } static extractUpdatePattern(node) { if (typescript_1.default.isBlock(node.body)) { const returnStatement = node.body.statements.find(typescript_1.default.isReturnStatement); return returnStatement?.expression?.getText() || null; } return node.body.getText(); } static findModifiedProperties(node) { const properties = new Set(); const visit = (n) => { if (typescript_1.default.isPropertyAssignment(n) && n.parent && typescript_1.default.isObjectLiteralExpression(n.parent)) { properties.add(n.name.getText()); } typescript_1.default.forEachChild(n, visit); }; visit(node); return Array.from(properties); } static isActionDispatch(node) { return (typescript_1.default.isIdentifier(node.expression) && (node.expression.text === "dispatch" || node.expression.text === "send")); } static extractActionPattern(node) { const arg = node.arguments[0]; if (arg) { return arg.getText(); } return null; } static findActionAffectedProperties(node) { const arg = node.arguments[0]; if (!arg) return []; if (typescript_1.default.isObjectLiteralExpression(arg)) { return this.extractAffectedProperties(arg); } if (typescript_1.default.isIdentifier(arg)) { // Try to find the action creator definition const definition = this.findActionCreatorDefinition(arg); if (definition) { return this.findModifiedProperties(definition); } } return []; } static findActionCreatorDefinition(identifier) { // This is a simplified version. In a real implementation, // you'd need to traverse the AST to find the actual definition return null; } } exports.StoreAnalysisUtils = StoreAnalysisUtils;