UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

281 lines (269 loc) 9.38 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_MONOREPO_STRUCTURE = void 0; exports.initializeMonorepo = initializeMonorepo; exports.getWorkspaces = getWorkspaces; exports.isMonorepoRoot = isMonorepoRoot; exports.findMonorepoRoot = findMonorepoRoot; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const yaml_1 = __importDefault(require("yaml")); const glob_1 = require("glob"); exports.DEFAULT_MONOREPO_STRUCTURE = { apps: 'apps', packages: 'packages', libs: 'libs', tools: 'tools', docs: 'docs', }; async function initializeMonorepo(name, packageManager = 'pnpm', customStructure) { const structure = { ...exports.DEFAULT_MONOREPO_STRUCTURE, ...customStructure }; const projectPath = path.resolve(process.cwd(), name); // Create root directory await fs.ensureDir(projectPath); // Create apps directory (main directory for microfrontend apps) await fs.ensureDir(path.join(projectPath, structure.apps)); const workspaces = [ `${structure.apps}/*`, `${structure.packages}/*`, `${structure.libs}/*`, `${structure.tools}/*`, ]; // Create root package.json const packageJson = { name, version: '0.1.0', description: `${name} - A multi-framework monorepo`, private: true, workspaces: packageManager === 'npm' ? { packages: workspaces } : workspaces, scripts: { dev: `${packageManager} run --parallel -r dev`, build: `${packageManager} run --parallel -r build`, lint: `${packageManager} run --parallel -r lint`, test: `${packageManager} run --parallel -r test`, clean: `${packageManager} run --parallel -r clean`, 'type-check': `${packageManager} run --parallel -r type-check`, 'workspace:list': 're-shell workspace list', 'workspace:graph': 're-shell workspace graph', 'workspace:update': 're-shell workspace update', }, devDependencies: { '@re-shell/cli': '^0.2.5', }, engines: { node: '>=16.0.0', }, }; await fs.writeFile(path.join(projectPath, 'package.json'), JSON.stringify(packageJson, null, 2)); // Create workspace configuration if (packageManager === 'pnpm') { const pnpmWorkspace = { packages: workspaces, }; await fs.writeFile(path.join(projectPath, 'pnpm-workspace.yaml'), yaml_1.default.stringify(pnpmWorkspace)); } else if (packageManager === 'yarn') { const yarnWorkspace = { workspaces: workspaces, }; await fs.writeFile(path.join(projectPath, 'package.json'), JSON.stringify({ ...packageJson, ...yarnWorkspace }, null, 2)); } // Create .gitignore const gitignore = `# Dependencies node_modules/ .pnp .pnp.js # Production builds dist/ build/ .next/ .nuxt/ .output/ # Environment variables .env .env.local .env.development.local .env.test.local .env.production.local # Logs npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log* # Runtime data pids *.pid *.seed *.pid.lock # Coverage directory used by tools like istanbul coverage/ *.lcov # nyc test coverage .nyc_output # IDE .vscode/ .idea/ *.swp *.swo # OS .DS_Store Thumbs.db # Temporary folders tmp/ temp/ # Cache .cache/ .parcel-cache/ .eslintcache .stylelintcache # TypeScript *.tsbuildinfo `; await fs.writeFile(path.join(projectPath, '.gitignore'), gitignore); return { name, packageManager, workspaces, structure, }; } async function getWorkspaces(rootPath = process.cwd()) { const packageJsonPath = path.join(rootPath, 'package.json'); if (!fs.existsSync(packageJsonPath)) { throw new Error('Not in a monorepo root (package.json not found)'); } const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')); let workspacePatterns = []; // Extract workspace patterns if (packageJson.workspaces) { if (Array.isArray(packageJson.workspaces)) { workspacePatterns = packageJson.workspaces; } else if (packageJson.workspaces.packages) { workspacePatterns = packageJson.workspaces.packages; } } // Check for pnpm-workspace.yaml const pnpmWorkspacePath = path.join(rootPath, 'pnpm-workspace.yaml'); if (fs.existsSync(pnpmWorkspacePath)) { const pnpmWorkspace = yaml_1.default.parse(await fs.readFile(pnpmWorkspacePath, 'utf8')); if (pnpmWorkspace.packages) { workspacePatterns = pnpmWorkspace.packages; } } const workspaces = []; // Find all workspace directories for (const pattern of workspacePatterns) { const matches = glob_1.glob.sync(pattern, { cwd: rootPath }); for (const match of matches) { const workspacePath = path.join(rootPath, match); const workspacePackageJson = path.join(workspacePath, 'package.json'); if (fs.existsSync(workspacePackageJson)) { try { const workspacePackage = JSON.parse(await fs.readFile(workspacePackageJson, 'utf8')); // Determine workspace type based on path let type = 'package'; if (match.startsWith('apps/')) type = 'app'; else if (match.startsWith('libs/')) type = 'lib'; else if (match.startsWith('tools/')) type = 'tool'; // Detect framework const framework = detectFrameworkFromPackage(workspacePackage); workspaces.push({ name: workspacePackage.name || path.basename(match), path: match, type, framework, version: workspacePackage.version || '0.0.0', dependencies: Object.keys({ ...workspacePackage.dependencies, ...workspacePackage.devDependencies, }), }); } catch (error) { console.warn(`Failed to parse package.json for ${match}:`, error); } } } } return workspaces; } function detectFrameworkFromPackage(packageJson) { const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; if (deps['@angular/core']) return 'angular'; if (deps['vue']) return deps['typescript'] ? 'vue-ts' : 'vue'; if (deps['svelte']) return deps['typescript'] ? 'svelte-ts' : 'svelte'; if (deps['react']) return deps['typescript'] ? 'react-ts' : 'react'; return undefined; } async function isMonorepoRoot(dirPath = process.cwd()) { const packageJsonPath = path.join(dirPath, 'package.json'); if (!fs.existsSync(packageJsonPath)) { return false; } try { const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8')); return !!(packageJson.workspaces || fs.existsSync(path.join(dirPath, 'pnpm-workspace.yaml'))); } catch { return false; } } async function findMonorepoRoot(startPath = process.cwd()) { let currentPath = path.resolve(startPath); const rootPath = path.parse(currentPath).root; let depth = 0; const maxDepth = 10; // Prevent searching too far up the filesystem while (currentPath !== rootPath && depth < maxDepth) { if (await isMonorepoRoot(currentPath)) { return currentPath; } currentPath = path.dirname(currentPath); depth++; } return null; }