@frontify/fondue
Version:
Design system of Frontify
259 lines (258 loc) • 7.07 kB
JavaScript
import { Command } from "commander";
import { writeFileSync, existsSync, rmSync, readFileSync } from "node:fs";
import path, { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { createRequire } from "node:module";
import { execa } from "execa";
const deprecated = [
"Accordion",
"AccordionHeaderIcon",
"AccordionHeaderProps",
"AccordionItem",
"ActionMenuProps",
"Breadcrumb",
"Breadcrumbs",
"CollapsibleWrap",
"Color",
"DatePicker",
"DatePickerProps",
"DatePickerTrigger",
"EditableMode",
"EditableText",
"EditableTextProps",
"FOCUS_VISIBLE_STYLE",
"FOCUS_VISIBLE_STYLE_INSET",
"FOCUS_WITHIN_STYLE",
"FilterableMultiSelect",
"FilterableMultiSelectItem",
"FilterableMultiSelectProps",
"FilterableMultiSelectSize",
"FilterableMultiSelectType",
"FormControl",
"FormControlDirection",
"FormControlProps",
"FormControlStyle",
"FrontifyPattern",
"HelperPosition",
"Item",
"LegacyTextarea",
"LegacyTextareaProps",
"MenuItem",
"MenuItemContentSize",
"MenuItemProps",
"MenuItemStyle",
"MenuItemType",
"MultiSelect",
"MultiSelectItem",
"MultiSelectProps",
"MultiSelectSize",
"MultiSelectType",
"OrderableList",
"OrderableListItem",
"OrderableListItemStyle",
"OrderableListProps",
"Palette",
"PatternDesign",
"PatternScale",
"PatternTheme",
"ReactDatePickerRef",
"RenderListItem",
"TABBABLE_ELEMENTS",
"Toast",
"ToastAnimationDirection",
"ToastStyle",
"Validation",
"useCopy",
"useForwardedRef",
"useMemoizedId",
"useMobileDetection"
];
const active = [
"AssetInput",
"AssetInputMenuBlock",
"AssetInputMenuDefaultItemType",
"AssetInputMenuItemContentProps",
"AssetInputMenuItemContentSize",
"AssetInputMenuItemProps",
"AssetInputMenuItemStyle",
"AssetInputMenuItemType",
"AssetInputMenuSwitchItemType",
"AssetInputProps",
"AssetInputSelectionIndicatorIcon",
"AssetInputSize",
"AssetType",
"CollapsibleWrap",
"CollisionPosition",
"DragHandle",
"DragHandleProps",
"DragHandlerPosition",
"EXPAND_ONHOVER_DELAY",
"ExpandButton",
"ExpandButtonProps",
"FilterableMultiSelect",
"INDENTATION_WIDTH",
"ImageAsset",
"InputLabelProps",
"InternalTreeItemMultiSelectProps",
"InternalTreeItemProps",
"LegacyTextarea",
"LibrarySource",
"MultiSelect",
"OnExpandCallback",
"OnSelectCallback",
"OnSelectInternalCallback",
"OnShrinkCallback",
"OnTreeDropCallback",
"OrderableList",
"PatternScaleOrigin",
"Projection",
"ProjectionArgs",
"ROOT_ID",
"RegisterNodeChildrenPayload",
"SensorContext",
"SortableProps",
"SortableTreeItemProps",
"Tree",
"TreeActive",
"TreeAnnouncements",
"TreeDragCancelEvent",
"TreeDragEndEvent",
"TreeDragMoveEvent",
"TreeDragOverEvent",
"TreeDragStartEvent",
"TreeItem",
"TreeItemBorderClassMap",
"TreeItemBorderRadiusClassMap",
"TreeItemBorderStyleClassMap",
"TreeItemColors",
"TreeItemColorsClassMap",
"TreeItemMultiselect",
"TreeItemMultiselectProps",
"TreeItemMultiselectWithNodes",
"TreeItemOverlay",
"TreeItemProps",
"TreeItemPropsSizing",
"TreeItemShadowClassMap",
"TreeItemSpacingClassMap",
"TreeItemState",
"TreeItemStyling",
"TreeItemWithContentComponentProps",
"TreeItemWithLabelProps",
"TreeNodeWithoutElements",
"TreeOver",
"TreeProps",
"TreeState",
"TreeStateAction",
"UploadSource",
"addSelectedIds",
"addSelectedItemsFromSelection",
"cleanOrphanSelectedIds",
"convertToPartialSelectedId",
"currentNodesChanged",
"extractNodeFromElement",
"findIndexById",
"fixParentSelectionState",
"getAnnouncements",
"getCurrentChildrenForNewNodesIfExpanded",
"getExtendedId",
"getMultiselectCheckBoxState",
"getNewSelectedItems",
"getNodeChildrenIds",
"getNodesToRender",
"getParentSelectedTreeItem",
"getProjection",
"getReactNodeIdsInFlatArray",
"getReactNodesInFlatArray",
"getSelectedChildrenItems",
"getSelectedTreeItem",
"getTreeNodesWithoutElements",
"getVerticalPositioning",
"handleKeyDownEvent",
"removePartialFlagSelectedId",
"removeReactNodesFromFlatArray",
"removeSelectedIds",
"sensorsActivationConstraint",
"shouldUpdateTreeState",
"updateNodeWithNewChildren",
"useTreeItem"
];
const detectedExports = {
deprecated,
active
};
const __dirname$2 = dirname(fileURLToPath(import.meta.url));
const require$1 = createRequire(import.meta.url);
const transformsDirectory = join(__dirname$2, "transforms");
const jscodeshiftExecutable = require$1.resolve(".bin/jscodeshift");
const runCodeshift = async (pathToAnalyze, transformName, options) => {
const transformPath = join(transformsDirectory, `${transformName}.ts`);
await execa(
jscodeshiftExecutable,
[
"--parser",
"tsx",
"--extensions",
"ts,tsx,js,jsx",
"--ignore-pattern",
"**/node_modules/**",
"--ignore-pattern",
"**/dist/**",
"--ignore-pattern",
"**/build/**",
"--ignore-pattern",
"**/.git/**",
"--ignore-pattern",
"**/public/**",
"--transform",
transformPath,
pathToAnalyze
],
{
env: {
...options
}
}
);
return;
};
const __dirname$1 = dirname(fileURLToPath(import.meta.url));
const tempDir = path.resolve(__dirname$1, "./temp");
const getImports = (pathToAnalyze, selectedImports = []) => {
if (existsSync(tempDir)) {
rmSync(tempDir, { recursive: true });
}
return runCodeshift(pathToAnalyze, "find-imports", {
selectedImports: selectedImports.join(","),
tempDir
}).then(() => {
if (existsSync(join(tempDir, "detected-imports.txt"))) {
const detectedImports = readFileSync(join(tempDir, "detected-imports.txt"), "utf8").split("\n").filter((line) => line.trim() !== "").map((line) => JSON.parse(line));
rmSync(join(tempDir), { recursive: true });
return detectedImports;
} else {
return [];
}
});
};
const findUnusedExports = (pathToAnalyze, outputPath, onlyDeprecated) => {
const fondueExports = [...detectedExports.deprecated, ...onlyDeprecated ? [] : detectedExports.active];
getImports(pathToAnalyze, fondueExports).then((detectedImports) => {
const unusedExports = fondueExports.filter(
(selectedExport) => !detectedImports.some((detectedImport) => detectedImport.imports.includes(selectedExport))
);
if (outputPath) {
writeFileSync(outputPath, JSON.stringify(unusedExports, null, 4), "utf8");
} else {
console.log(unusedExports);
}
}).catch((error) => {
console.error("ERROR", error);
});
};
const program = new Command();
program.name("fondue-analyzer").description("Analyze fondue usage");
program.command("find-unused-exports").description("Find unused fondue exports").argument("<path>", "Path to be analyzed").option("--only-deprecated", "Only find unused deprecated exports").option("-o, --output <path>", "Output path").action((path2, options) => {
findUnusedExports(path2, options.output, options.onlyDeprecated);
});
program.parse();