mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:21:10 +02:00
🔧 chore: enforce monorepo best practices with automated validation
Fix critical issues and add validation to prevent future violations: **Fixes:** - Remove turbo recursion in 5 app packages (infinite loop risk) - Add "private": true to 11 packages (prevent accidental publishing) - Rename @mana-core/nestjs-integration → @manacore/nestjs-integration - Remove prepublishOnly scripts from 3 private packages **New:** - Add scripts/validate-monorepo.mjs with 4 critical checks - Add validate:monorepo command to package.json - Integrate validation into CI pipeline (.github/workflows/ci.yml) - Document validation in CLAUDE.md All 80 package.json files now pass validation ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
079b55a796
commit
5b7d3c649b
29 changed files with 304 additions and 25 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
|
@ -51,6 +51,9 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Validate monorepo best practices
|
||||
run: pnpm run validate:monorepo
|
||||
|
||||
- name: Type check
|
||||
run: pnpm run type-check
|
||||
|
||||
|
|
|
|||
29
CLAUDE.md
29
CLAUDE.md
|
|
@ -149,12 +149,41 @@ Generated from `.env.development` via `pnpm setup:env` (auto-runs after install)
|
|||
pnpm install # Install dependencies
|
||||
pnpm dev:{app}:full # Start app with DB setup
|
||||
pnpm type-check # Type check all packages
|
||||
pnpm lint # Lint all packages
|
||||
pnpm format # Format code
|
||||
pnpm build # Build all packages
|
||||
pnpm docker:up # Start local infrastructure
|
||||
pnpm setup:env # Regenerate .env files
|
||||
pnpm validate:monorepo # Validate monorepo best practices
|
||||
```
|
||||
|
||||
## Validation & CI
|
||||
|
||||
### Monorepo Best Practices Validation
|
||||
|
||||
The `validate:monorepo` command checks for common monorepo issues:
|
||||
|
||||
```bash
|
||||
pnpm validate:monorepo
|
||||
```
|
||||
|
||||
**What it checks:**
|
||||
1. **No Turborepo recursion** - Ensures child packages don't have `turbo run` commands (prevents infinite loops)
|
||||
2. **Private packages** - All internal packages in `packages/` and `services/` have `"private": true`
|
||||
3. **Workspace protocol** - All internal dependencies use `workspace:*` (no hardcoded versions)
|
||||
4. **No obsolete scripts** - Warns about `prepublishOnly` in private packages
|
||||
|
||||
**When it runs:**
|
||||
- Locally: `pnpm validate:monorepo`
|
||||
- CI/CD: Automatically on every PR (`.github/workflows/ci.yml`)
|
||||
|
||||
**Example output:**
|
||||
```
|
||||
✅ All checks passed! Monorepo follows best practices.
|
||||
```
|
||||
|
||||
This prevents issues before they reach production! 🛡️
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Code Patterns:** [.claude/GUIDELINES.md](.claude/GUIDELINES.md) - Detailed technical guidelines
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"private": true,
|
||||
"description": "Calendar App - Personal and Shared Calendars with CalDAV/iCal Sync",
|
||||
"scripts": {
|
||||
"dev": "turbo run dev",
|
||||
"dev": "pnpm run --filter=@calendar/* --parallel dev",
|
||||
"dev:backend": "pnpm --filter @calendar/backend dev",
|
||||
"dev:web": "pnpm --filter @calendar/web dev",
|
||||
"dev:landing": "pnpm --filter @calendar/landing dev",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
"private": true,
|
||||
"description": "Chat project - AI chat application with mobile, web and landing",
|
||||
"scripts": {
|
||||
"dev": "turbo run dev"
|
||||
"dev": "pnpm run --filter=@chat/* --parallel dev"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"private": true,
|
||||
"description": "Contacts App - Contact Management with Manacore Integration",
|
||||
"scripts": {
|
||||
"dev": "turbo run dev",
|
||||
"dev": "pnpm run --filter=@contacts/* --parallel dev",
|
||||
"dev:backend": "pnpm --filter @contacts/backend dev",
|
||||
"dev:web": "pnpm --filter @contacts/web dev",
|
||||
"dev:landing": "pnpm --filter @contacts/landing dev",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "turbo run dev"
|
||||
"dev": "pnpm --filter @context/mobile dev"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mana-core/nestjs-integration": "workspace:*",
|
||||
"@manacore/nestjs-integration": "workspace:*",
|
||||
"@manacore/shared-errors": "workspace:*",
|
||||
"@google/genai": "^1.14.0",
|
||||
"@manacore/manadeck-database": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
|||
import { ClsModule } from 'nestjs-cls';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
import { HttpModule } from '@nestjs/axios';
|
||||
import { ManaCoreModule } from '@mana-core/nestjs-integration';
|
||||
import { ManaCoreModule } from '@manacore/nestjs-integration';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { ApiController } from './controllers/api.controller';
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import {
|
|||
Logger,
|
||||
BadRequestException,
|
||||
} from '@nestjs/common';
|
||||
import { AuthGuard } from '@mana-core/nestjs-integration/guards';
|
||||
import { CurrentUser } from '@mana-core/nestjs-integration/decorators';
|
||||
import { CreditClientService } from '@mana-core/nestjs-integration';
|
||||
import { AuthGuard } from '@manacore/nestjs-integration/guards';
|
||||
import { CurrentUser } from '@manacore/nestjs-integration/decorators';
|
||||
import { CreditClientService } from '@manacore/nestjs-integration';
|
||||
import { isOk, CreditError, ServiceError } from '@manacore/shared-errors';
|
||||
import {
|
||||
CreditOperationType,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Controller, Get } from '@nestjs/common';
|
||||
import { HealthCheckService, HttpHealthIndicator, HealthCheck } from '@nestjs/terminus';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Public } from '@mana-core/nestjs-integration/decorators';
|
||||
import { Public } from '@manacore/nestjs-integration/decorators';
|
||||
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Controller, Get, UseGuards, Query, Logger } from '@nestjs/common';
|
||||
import { OptionalAuthGuard } from '@mana-core/nestjs-integration/guards';
|
||||
import { CurrentUser, Public } from '@mana-core/nestjs-integration/decorators';
|
||||
import { OptionalAuthGuard } from '@manacore/nestjs-integration/guards';
|
||||
import { CurrentUser, Public } from '@manacore/nestjs-integration/decorators';
|
||||
import { DeckRepository, UserStatsRepository, DeckTemplateRepository } from '../database';
|
||||
|
||||
@Controller('public')
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.700.0",
|
||||
"@mana-core/nestjs-integration": "workspace:*",
|
||||
"@manacore/nestjs-integration": "workspace:*",
|
||||
"@manacore/shared-errors": "workspace:*",
|
||||
"@manacore/shared-nestjs-auth": "workspace:*",
|
||||
"@manacore/shared-nestjs-cors": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { ManaCoreModule } from '@mana-core/nestjs-integration';
|
||||
import { ManaCoreModule } from '@manacore/nestjs-integration';
|
||||
import { DatabaseModule } from './db/database.module';
|
||||
import { HealthModule } from './health/health.module';
|
||||
import { ModelModule } from './model/model.module';
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
} from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { CreditClientService } from '@mana-core/nestjs-integration';
|
||||
import { CreditClientService } from '@manacore/nestjs-integration';
|
||||
import { DATABASE_CONNECTION } from '../db/database.module';
|
||||
import { Database } from '../db/connection';
|
||||
import { imageGenerations, images, models } from '../db/schema';
|
||||
|
|
|
|||
|
|
@ -4,13 +4,10 @@
|
|||
"private": true,
|
||||
"description": "Todo App - Task Management for ManaCore Ecosystem",
|
||||
"scripts": {
|
||||
"dev": "turbo run dev",
|
||||
"dev": "pnpm run --filter=@todo/* --parallel dev",
|
||||
"dev:backend": "pnpm --filter @todo/backend dev",
|
||||
"dev:web": "pnpm --filter @todo/web dev",
|
||||
"dev:landing": "pnpm --filter @todo/landing dev",
|
||||
"build": "turbo run build",
|
||||
"lint": "turbo run lint",
|
||||
"clean": "turbo run clean",
|
||||
"db:push": "pnpm --filter @todo/backend db:push",
|
||||
"db:studio": "pnpm --filter @todo/backend db:studio",
|
||||
"db:seed": "pnpm --filter @todo/backend db:seed"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
"clean": "turbo run clean",
|
||||
"format": "prettier --config .prettierrc.json --write \"**/*.{ts,tsx,js,jsx,json,md,svelte,astro}\"",
|
||||
"format:check": "prettier --config .prettierrc.json --check \"**/*.{ts,tsx,js,jsx,json,md,svelte,astro}\"",
|
||||
"validate:monorepo": "node scripts/validate-monorepo.mjs",
|
||||
"validate:runtime-config": "node scripts/validate-runtime-config.mjs",
|
||||
"svelte-check": "./scripts/svelte-check-staged.sh",
|
||||
"build:check": "./scripts/build-check-staged.sh",
|
||||
|
|
@ -160,8 +161,8 @@
|
|||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
"allowedVersions": {
|
||||
"@mana-core/nestjs-integration>@nestjs/common": "^11.0.0",
|
||||
"@mana-core/nestjs-integration>@nestjs/core": "^11.0.0",
|
||||
"@manacore/nestjs-integration>@nestjs/common": "^11.0.0",
|
||||
"@manacore/nestjs-integration>@nestjs/core": "^11.0.0",
|
||||
"react-native>react": ">=18.0.0",
|
||||
"react-native>@types/react": ">=18.0.0",
|
||||
"@sveltejs/vite-plugin-svelte>vite": ">=6.0.0",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/better-auth-types",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Centralized Better Auth type definitions for the Mana Core monorepo",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@mana-core/nestjs-integration",
|
||||
"name": "@manacore/nestjs-integration",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "NestJS integration package for Mana Core authentication and credits",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/shared-auth-stores",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/shared-auth-ui",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Shared authentication UI components for Mana apps",
|
||||
"type": "module",
|
||||
"svelte": "./src/index.ts",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/shared-auth",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Shared authentication utilities for Manacore apps",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/shared-credit-service",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/shared-error-tracking",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Centralized error tracking for ManaCore applications - NestJS and frontend clients",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
@ -25,7 +26,6 @@
|
|||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rm -rf dist",
|
||||
"prepublishOnly": "pnpm build",
|
||||
"lint": "eslint .",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/shared-landing-ui",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Shared Astro landing page components for Manacore monorepo",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"name": "@manacore/shared-nestjs-auth",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Shared authentication utilities for NestJS backends - JWT validation via Mana Core Auth",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rm -rf dist",
|
||||
"prepublishOnly": "pnpm build",
|
||||
"lint": "eslint .",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
"build": "tsc",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rm -rf dist",
|
||||
"prepublishOnly": "pnpm build",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "@manacore/shared-tags",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Shared tags client for Manacore apps - connects to central tags service",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
|
|||
241
scripts/validate-monorepo.mjs
Executable file
241
scripts/validate-monorepo.mjs
Executable file
|
|
@ -0,0 +1,241 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Validate Monorepo Best Practices
|
||||
*
|
||||
* Checks:
|
||||
* 1. No "turbo run" commands in child package.json files (prevents infinite loops)
|
||||
* 2. All internal packages have "private": true
|
||||
* 3. All internal dependencies use "workspace:*" protocol
|
||||
* 4. No prepublishOnly scripts in private packages
|
||||
*/
|
||||
|
||||
import { readFileSync, readdirSync, statSync } from 'fs';
|
||||
import { join, relative } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname } from 'path';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const MONOREPO_ROOT = join(__dirname, '..');
|
||||
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
// Colors for terminal output
|
||||
const RED = '\x1b[31m';
|
||||
const YELLOW = '\x1b[33m';
|
||||
const GREEN = '\x1b[32m';
|
||||
const RESET = '\x1b[0m';
|
||||
|
||||
/**
|
||||
* Find all package.json files in the monorepo
|
||||
*/
|
||||
function findPackageJsonFiles(dir, files = []) {
|
||||
const entries = readdirSync(dir);
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(dir, entry);
|
||||
const stat = statSync(fullPath);
|
||||
|
||||
// Skip node_modules and hidden directories
|
||||
if (entry === 'node_modules' || entry.startsWith('.')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
findPackageJsonFiles(fullPath, files);
|
||||
} else if (entry === 'package.json') {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a package.json has turbo run commands (infinite loop risk)
|
||||
*/
|
||||
function checkTurboRecursion(packagePath, packageJson) {
|
||||
const relativePath = relative(MONOREPO_ROOT, packagePath);
|
||||
|
||||
// Skip root package.json
|
||||
if (relativePath === 'package.json') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if package is in apps/, games/, packages/, or services/
|
||||
const isChildPackage =
|
||||
relativePath.startsWith('apps/') ||
|
||||
relativePath.startsWith('games/') ||
|
||||
relativePath.startsWith('packages/') ||
|
||||
relativePath.startsWith('services/');
|
||||
|
||||
if (!isChildPackage) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scripts = packageJson.scripts || {};
|
||||
|
||||
for (const [scriptName, scriptCommand] of Object.entries(scripts)) {
|
||||
if (typeof scriptCommand === 'string' && scriptCommand.includes('turbo run')) {
|
||||
// Exception: "dev" script with turbo run is sometimes OK if it filters correctly
|
||||
if (scriptName === 'dev' && scriptCommand.includes('--filter')) {
|
||||
warnings.push(
|
||||
`⚠️ ${relativePath}: "dev" script uses "turbo run" with --filter. Make sure it doesn't create infinite loops.`
|
||||
);
|
||||
} else {
|
||||
errors.push(
|
||||
`❌ ${relativePath}: "${scriptName}" script contains "turbo run" which can cause infinite loops. Remove it and let root turbo.json handle orchestration.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all internal packages are marked private
|
||||
*/
|
||||
function checkPrivateFlag(packagePath, packageJson) {
|
||||
const relativePath = relative(MONOREPO_ROOT, packagePath);
|
||||
|
||||
// Skip root
|
||||
if (relativePath === 'package.json') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only check packages in packages/ and services/
|
||||
const isInternalPackage =
|
||||
relativePath.startsWith('packages/') || relativePath.startsWith('services/');
|
||||
|
||||
if (!isInternalPackage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (packageJson.private !== true) {
|
||||
errors.push(
|
||||
`❌ ${relativePath}: Missing "private": true. All internal packages should be private to prevent accidental npm publishing.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all internal dependencies use workspace protocol
|
||||
*/
|
||||
function checkWorkspaceProtocol(packagePath, packageJson) {
|
||||
const relativePath = relative(MONOREPO_ROOT, packagePath);
|
||||
|
||||
// Skip root
|
||||
if (relativePath === 'package.json') {
|
||||
return;
|
||||
}
|
||||
|
||||
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
||||
const internalScopes = [
|
||||
'@manacore/',
|
||||
'@mana-core/',
|
||||
'@chat/',
|
||||
'@picture/',
|
||||
'@calendar/',
|
||||
'@contacts/',
|
||||
'@todo/',
|
||||
'@manadeck/',
|
||||
'@zitare/',
|
||||
'@voxel-lava/',
|
||||
'@mana-games/',
|
||||
'@figgos/',
|
||||
'@worldream/',
|
||||
'@context/',
|
||||
];
|
||||
|
||||
for (const [depName, depVersion] of Object.entries(deps)) {
|
||||
// Check if dependency is internal
|
||||
const isInternal = internalScopes.some((scope) => depName.startsWith(scope));
|
||||
|
||||
if (isInternal && !depVersion.startsWith('workspace:')) {
|
||||
errors.push(
|
||||
`❌ ${relativePath}: Dependency "${depName}" should use "workspace:*" instead of "${depVersion}"`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for prepublishOnly scripts in private packages
|
||||
*/
|
||||
function checkPrepublishOnlyScripts(packagePath, packageJson) {
|
||||
const relativePath = relative(MONOREPO_ROOT, packagePath);
|
||||
|
||||
// Skip root
|
||||
if (relativePath === 'package.json') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only check private packages
|
||||
if (packageJson.private !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scripts = packageJson.scripts || {};
|
||||
|
||||
if (scripts.prepublishOnly) {
|
||||
warnings.push(
|
||||
`⚠️ ${relativePath}: Has "prepublishOnly" script but is marked private. This script won't execute. Consider removing it.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main validation function
|
||||
*/
|
||||
function validateMonorepo() {
|
||||
console.log('🔍 Validating Monorepo Best Practices...\n');
|
||||
|
||||
const packageJsonFiles = findPackageJsonFiles(MONOREPO_ROOT);
|
||||
|
||||
for (const packagePath of packageJsonFiles) {
|
||||
try {
|
||||
const content = readFileSync(packagePath, 'utf-8');
|
||||
const packageJson = JSON.parse(content);
|
||||
|
||||
checkTurboRecursion(packagePath, packageJson);
|
||||
checkPrivateFlag(packagePath, packageJson);
|
||||
checkWorkspaceProtocol(packagePath, packageJson);
|
||||
checkPrepublishOnlyScripts(packagePath, packageJson);
|
||||
} catch (error) {
|
||||
errors.push(`❌ Failed to parse ${relative(MONOREPO_ROOT, packagePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Print results
|
||||
console.log(`\n📊 Validation Results:`);
|
||||
console.log(` Checked ${packageJsonFiles.length} package.json files\n`);
|
||||
|
||||
if (errors.length === 0 && warnings.length === 0) {
|
||||
console.log(`${GREEN}✅ All checks passed! Monorepo follows best practices.${RESET}\n`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.log(`${RED}❌ Found ${errors.length} error(s):${RESET}\n`);
|
||||
errors.forEach((error) => console.log(` ${error}`));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
if (warnings.length > 0) {
|
||||
console.log(`${YELLOW}⚠️ Found ${warnings.length} warning(s):${RESET}\n`);
|
||||
warnings.forEach((warning) => console.log(` ${warning}`));
|
||||
console.log('');
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.log(`${RED}❌ Validation failed. Please fix the errors above.${RESET}\n`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`${GREEN}✅ Validation passed with warnings. Consider fixing them.${RESET}\n`);
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Run validation
|
||||
validateMonorepo();
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"name": "mana-core-auth",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Mana Core Authentication and Credit System",
|
||||
"main": "dist/main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue