UNPKG

@react-native-paper-abstracted/cli

Version:

React Native Paper Abstracted is a package that allows you to use only the components you need from [React Native Paper](https://reactnativepaper.com). Thus allowing users to keep their app size small, and provides endless customization.

249 lines (212 loc) 7.97 kB
import path from "path"; import fs from "fs-extra"; import pc from "picocolors"; import { exec } from "child_process"; import { promisify } from "util"; import { _spinner } from "./spinners.js"; import { OWNER, REPO_CORE } from "./constants.js"; import { ensureString, handleSaveToFolder, processDirectory } from "./index.js"; const spinner = _spinner(); const execAsync = promisify(exec); const cloneRepo = async (repoName: string, targetPath: string, sparsePath: string, otherSparsePath = "") => { await execAsync( `git clone --depth 1 --filter=blob:none --sparse https://github.com/${OWNER}/${repoName}.git ${targetPath}`, ); await execAsync( `cd ${targetPath} && git sparse-checkout set ${sparsePath} ${otherSparsePath} --skip-checks`, ); }; const CORE_COMPONENTS = [ { path: "packages/core/src/core", relativeParentPath: "src" }, { path: "packages/core/src/styles", relativeParentPath: "src" }, { path: "packages/core/src/utils", relativeParentPath: "src" }, { path: "packages/core/src/components/MaterialCommunityIcon", relativeParentPath: "src/components" }, { path: "packages/core/src/components/Portal", relativeParentPath: "src/components" }, { path: "packages/core/src/types.tsx", relativeParentPath: "src" }, { path: "packages/core/src/constants.tsx", relativeParentPath: "src" }, ]; // const OTHER_SPARSES = CORE_COMPONENTS.slice(1).join(" "); export const initProject = async (outDir: string, spinner: ReturnType<typeof _spinner>) => { let tempCoreDir: string = ""; try { // spinner.start(); // Create the base output directory fs.mkdirSync(outDir, { recursive: true }); // Handle core components const corePath = path.join(outDir); // Set up temp directory for core tempCoreDir = path.join(outDir, "_temp_core"); if (fs.existsSync(tempCoreDir)) { fs.rmSync(tempCoreDir, { recursive: true, force: true }); } fs.mkdirSync(tempCoreDir); const progressCallback = (progress: number, currentFileOrFolderName?: string) => { spinner.fetch(`Fetching ${currentFileOrFolderName}...`); if (progress === 100) spinner.succeed("Done"); }; const coreComponentsPath: string[] = []; for (let { path: i, relativeParentPath } of CORE_COMPONENTS) { const installedPath = await handleSaveToFolder({ outDir, log: false, progressCallback, absoluteComponentPath: i, relativeParentFolderPath: relativeParentPath, }); coreComponentsPath.push(path.join(corePath, path.basename(i))); if (installedPath) { console.log(`${pc.green("✔︎")} ${pc.bold("Output Dir")}: ${pc.cyan(installedPath)}`); } } // Clone and process core // await cloneRepo( // REPO_CORE, // tempCoreDir, // "packages/core/src/core", // OTHER_SPARSES, // ); // Move core files to final location // fs.mkdirSync(corePath, { recursive: true }); // for (let i of CORE_COMPONENTS) { // // If sparse is a file omit -r flag // if (corePath.includes(".")) { // await execAsync( // `cp ${path.join(tempCoreDir, i)} ${corePath}`, // ); // } else { // await execAsync( // `cp -r ${path.join(tempCoreDir, i)} ${corePath}`, // ); // } // coreComponentsPath.push(path.join(corePath, path.basename(i))); // } // Process the core components, and update imports const relativeOutDir = path.join(process.cwd(), outDir); await processDirectory(coreComponentsPath, relativeOutDir); // Clean up core temp directory fs.rmSync(tempCoreDir, { recursive: true, force: true }); // spinner.succeed("Done"); } catch (error: any) { if (tempCoreDir) { fs.rmSync(tempCoreDir, { recursive: true, force: true }); } console.log(error); spinner.fail("Download failed"); } }; const removeTestFiles = async (filePath: string) => { try { const fileNames = fs.readdirSync(filePath, { encoding: "utf8", recursive: true }); for (let fileName of fileNames) { // For some reason fs cannot delete empty __tests__ folder if (fileName.includes("__test__") || fileName.includes("__tests__") && fileName !== "__tests__") { const testFilePath = path.join(filePath, fileName); if (fs.existsSync(testFilePath)) { fs.rmSync(testFilePath, { recursive: true }); } } } } catch (err: any) { console.log(pc.red(err)); } }; export const cloneSpecificFolder = async ( { msg, repo, outDir, otherSparses, unwantedFolders, remoteComponentFolderPath, }: { msg?: string; repo: string; outDir: string; otherSparses?: string; unwantedFolders?: string[]; remoteComponentFolderPath: string; }, ) => { let tempDir: string = ""; try { spinner.initialize(); // Create the base output directory fs.mkdirSync(outDir, { recursive: true }); // Handle component tempDir = path.join(outDir, "_temp"); if (fs.existsSync(tempDir)) { fs.rmSync(tempDir, { recursive: true, force: true }); } fs.mkdirSync(tempDir); spinner.succeed(); // Get components spinner.fetch(msg || "Fetching components..."); await cloneRepo(repo, tempDir, remoteComponentFolderPath, otherSparses); spinner.succeed("Fetching: Done..."); spinner.start("Setting up..."); // Set up component directory const componentDir = outDir; fs.mkdirSync(componentDir, { recursive: true }); // Remove unwanted folder e.g foo/bar/scripts if (unwantedFolders?.length) { for (const i of unwantedFolders) { try { await execAsync( `rm -rf ${path.join(tempDir, i)}`, ); } catch (err) { console.log(err); } } } // Copy component files from temp folder to actual location const sparses = otherSparses ? otherSparses.split(" ") || [] : []; const coreComponentsPath: string[] = []; if (sparses.length) { for (const s of [...sparses, remoteComponentFolderPath]) { if (s === outDir) { await execAsync(`cp -r ${path.join(tempDir, s)}/* ${componentDir}`); } else { if (s.includes(".")) { await execAsync(`cp ${path.join(tempDir, s)} ${componentDir}/`); } else { await execAsync(`cp -r ${path.join(tempDir, s)} ${componentDir}/`); } } // Use the actual folder or file name of the core component(s) when // processing. Since they the are moved to the outdir as foo/core-folder-or file // and not foo/core/src/core-folder-or-file const componentFolderOrFileName = ensureString(s.split("src/").pop()); coreComponentsPath.push(path.join(outDir, componentFolderOrFileName)); } } else { await execAsync( `cp -rf ${path.join(tempDir, remoteComponentFolderPath)}/* ${componentDir}/`, ); } // Cleanup and process fs.rmSync(tempDir, { recursive: true, force: true }); // const allSparses = [...(otherSparses?.split(" ") || []), remoteComponentFolderPath]; // const sparsesWithRelativePath = allSparses.map((s) => path.join(outDir, s)) || []; const relativeOutDir = path.join(process.cwd(), outDir); await processDirectory(coreComponentsPath, relativeOutDir); removeTestFiles(componentDir); spinner.succeed("Setting up: Done..."); return componentDir; } catch (error: any) { // Stop spinners spinner.stop(); // Clean up both temp directories if they exist if (tempDir) { fs.rmSync(tempDir, { recursive: true, force: true }); } if (error.message.includes("No such file or directory")) { console.log( pc.green( `Hint: Probably ${pc.bold(remoteComponentFolderPath)} or ${pc.bold(outDir)} is not a valid component name`, ), ); } console.error(error.message); } };