chore: improved clean commands which work on windows and output pretty summary (#6685)
This commit is contained in:
11
package.json
11
package.json
@@ -9,6 +9,7 @@
|
|||||||
"build:app": "next build",
|
"build:app": "next build",
|
||||||
"build:app:analyze": "cross-env ANALYZE=true next build",
|
"build:app:analyze": "cross-env ANALYZE=true next build",
|
||||||
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\"",
|
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\"",
|
||||||
|
"build:core:force": "pnpm clean:build && turbo build --filter \"!@payloadcms/plugin-*\" --no-cache --force",
|
||||||
"build:create-payload-app": "turbo build --filter create-payload-app",
|
"build:create-payload-app": "turbo build --filter create-payload-app",
|
||||||
"build:db-mongodb": "turbo build --filter db-mongodb",
|
"build:db-mongodb": "turbo build --filter db-mongodb",
|
||||||
"build:db-postgres": "turbo build --filter db-postgres",
|
"build:db-postgres": "turbo build --filter db-postgres",
|
||||||
@@ -42,21 +43,21 @@
|
|||||||
"build:translations": "turbo build --filter translations",
|
"build:translations": "turbo build --filter translations",
|
||||||
"build:ui": "turbo build --filter ui",
|
"build:ui": "turbo build --filter ui",
|
||||||
"clean": "turbo clean",
|
"clean": "turbo clean",
|
||||||
"clean:all": "find . \\( -type d \\( -name node_modules -o -name dist -o -name .cache -o -name .next -o -name .turbo \\) -o -type f -name tsconfig.tsbuildinfo \\) -exec rm -rf {} +",
|
"clean:all": "node ./scripts/delete-recursively.js '@node_modules' 'media' '**/dist' '**/.cache' '**/.next' '**/.turbo' '**/tsconfig.tsbuildinfo' '**/payload*.tgz'",
|
||||||
"clean:build": "find . \\( -type d \\( -name dist -o -name .cache -o -name .next -o -name .turbo \\) -o -type f -name tsconfig.tsbuildinfo \\) -not -path '*/node_modules/*' -exec rm -rf {} +",
|
"clean:build": "node ./scripts/delete-recursively.js 'media' '**/dist' '**/.cache' '**/.next' '**/.turbo' '**/tsconfig.tsbuildinfo' '**/payload*.tgz'",
|
||||||
"clean:cache": "rimraf node_modules/.cache && rimraf packages/payload/node_modules/.cache && rimraf .next",
|
"clean:cache": "node ./scripts/delete-recursively.js node_modules/.cache! packages/payload/node_modules/.cache! .next",
|
||||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation node ./test/dev.js",
|
"dev": "cross-env NODE_OPTIONS=--no-deprecation node ./test/dev.js",
|
||||||
"dev:generate-graphql-schema": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/generateGraphQLSchema.ts",
|
"dev:generate-graphql-schema": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/generateGraphQLSchema.ts",
|
||||||
"dev:generate-types": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/generateTypes.ts",
|
"dev:generate-types": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/generateTypes.ts",
|
||||||
"dev:postgres": "cross-env NODE_OPTIONS=--no-deprecation PAYLOAD_DATABASE=postgres node ./test/dev.js",
|
"dev:postgres": "cross-env NODE_OPTIONS=--no-deprecation PAYLOAD_DATABASE=postgres node ./test/dev.js",
|
||||||
"devsafe": "rimraf .next && pnpm dev",
|
"devsafe": "node ./scripts/delete-recursively.js '**/.next' && pnpm dev",
|
||||||
"docker:restart": "pnpm docker:stop --remove-orphans && pnpm docker:start",
|
"docker:restart": "pnpm docker:stop --remove-orphans && pnpm docker:start",
|
||||||
"docker:start": "docker compose -f packages/plugin-cloud-storage/docker-compose.yml up -d",
|
"docker:start": "docker compose -f packages/plugin-cloud-storage/docker-compose.yml up -d",
|
||||||
"docker:stop": "docker compose -f packages/plugin-cloud-storage/docker-compose.yml down",
|
"docker:stop": "docker compose -f packages/plugin-cloud-storage/docker-compose.yml down",
|
||||||
"fix": "eslint \"packages/**/*.ts\" --fix",
|
"fix": "eslint \"packages/**/*.ts\" --fix",
|
||||||
"lint": "eslint \"packages/**/*.ts\"",
|
"lint": "eslint \"packages/**/*.ts\"",
|
||||||
"lint-staged": "lint-staged",
|
"lint-staged": "lint-staged",
|
||||||
"obliterate-playwright-cache": "rm -rf ~/Library/Caches/ms-playwright && find /System/Volumes/Data/private/var/folders -type d -name 'playwright*' -exec rm -rf {} +",
|
"obliterate-playwright-cache-macos": "rm -rf ~/Library/Caches/ms-playwright && find /System/Volumes/Data/private/var/folders -type d -name 'playwright*' -exec rm -rf {} +",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"reinstall": "pnpm clean:all && pnpm install",
|
"reinstall": "pnpm clean:all && pnpm install",
|
||||||
"release:alpha": "tsx ./scripts/release.ts --bump prerelease --tag alpha",
|
"release:alpha": "tsx ./scripts/release.ts --bump prerelease --tag alpha",
|
||||||
|
|||||||
157
scripts/delete-recursively.js
Normal file
157
scripts/delete-recursively.js
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
import { promises as fs, existsSync } from 'fs'
|
||||||
|
import path, { join } from 'path'
|
||||||
|
import glob from 'glob'
|
||||||
|
import process from 'process'
|
||||||
|
import chalk from 'chalk'
|
||||||
|
|
||||||
|
// Helper function to format size appropriately in KB or MB
|
||||||
|
function formatSize(sizeInBytes) {
|
||||||
|
const sizeInKB = sizeInBytes / 1024
|
||||||
|
if (sizeInKB < 1024) {
|
||||||
|
return `${sizeInKB.toFixed(2)} KB`
|
||||||
|
} else {
|
||||||
|
return `${(sizeInKB / 1024).toFixed(2)} MB`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to calculate the size of a directory
|
||||||
|
async function calculateSize(targetPath) {
|
||||||
|
let totalSize = 0
|
||||||
|
const stats = await fs.lstat(targetPath)
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
const files = await fs.readdir(targetPath)
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = join(targetPath, file)
|
||||||
|
totalSize += await calculateSize(filePath)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
totalSize = stats.size
|
||||||
|
}
|
||||||
|
return totalSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to delete a file or directory recursively
|
||||||
|
async function deleteRecursively(targetPath, fullDelete = false) {
|
||||||
|
try {
|
||||||
|
if (fullDelete && existsSync(targetPath)) {
|
||||||
|
const size = await calculateSize(targetPath)
|
||||||
|
await fs.rmdir(targetPath, { recursive: true }) // Use async version of rmdir
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
const stats = await fs.lstat(targetPath)
|
||||||
|
let size = 0
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
const files = await fs.readdir(targetPath)
|
||||||
|
for (const file of files) {
|
||||||
|
const curPath = join(targetPath, file)
|
||||||
|
size += await deleteRecursively(curPath)
|
||||||
|
}
|
||||||
|
await fs.rmdir(targetPath)
|
||||||
|
} else {
|
||||||
|
size = stats.size
|
||||||
|
await fs.unlink(targetPath)
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
} catch (error) {
|
||||||
|
console.error(chalk.red(`Error deleting ${targetPath}: ${error.message}`))
|
||||||
|
return 0 // Return 0 size if there's an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to clean directories based on provided patterns
|
||||||
|
async function cleanDirectories(patterns) {
|
||||||
|
const deletedCounts = {}
|
||||||
|
let totalSize = 0
|
||||||
|
|
||||||
|
for (let entry of patterns) {
|
||||||
|
const ignoreNodeModules = !entry.endsWith('!')
|
||||||
|
let pattern = ignoreNodeModules ? entry : entry.slice(0, -1)
|
||||||
|
|
||||||
|
let files = []
|
||||||
|
let fulleDelete = false
|
||||||
|
if (pattern === '@node_modules') {
|
||||||
|
pattern = '**/node_modules'
|
||||||
|
fulleDelete = true
|
||||||
|
files = await new Promise((resolve, reject) => {
|
||||||
|
glob(pattern, { nodir: false }, (err, files) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
// Filter out node_modules within other node_modules
|
||||||
|
const topNodeModules = files.filter((file) => {
|
||||||
|
const parentDir = path.dirname(file)
|
||||||
|
return !parentDir.includes('node_modules')
|
||||||
|
})
|
||||||
|
resolve(topNodeModules)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const options = {
|
||||||
|
ignore: ignoreNodeModules ? '**/node_modules/**' : '',
|
||||||
|
nodir: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
files = await new Promise((resolve, reject) => {
|
||||||
|
glob(pattern, options, (err, files) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(files)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = 0
|
||||||
|
let patternSize = 0
|
||||||
|
for (const file of files) {
|
||||||
|
const fileSize = await deleteRecursively(file, fulleDelete)
|
||||||
|
count++
|
||||||
|
patternSize += fileSize
|
||||||
|
}
|
||||||
|
deletedCounts[pattern] = { count, size: patternSize }
|
||||||
|
totalSize += patternSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the maximum lengths needed for even spacing
|
||||||
|
const maxPatternLength = Math.max(...Object.keys(deletedCounts).map((pattern) => pattern.length))
|
||||||
|
const maxCountLength = Math.max(
|
||||||
|
...Object.values(deletedCounts).map(
|
||||||
|
(item) => `${item.count} item${item.count !== 1 ? 's' : ''} deleted`.length,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
const maxSizeLength = Math.max(
|
||||||
|
...Object.values(deletedCounts).map((item) => formatSize(item.size).length),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Print details for each pattern with colors, formatted for alignment
|
||||||
|
console.log(chalk.blue('Summary of deleted items:'))
|
||||||
|
Object.keys(deletedCounts).forEach((pattern) => {
|
||||||
|
const itemCount =
|
||||||
|
`${deletedCounts[pattern].count} item${deletedCounts[pattern].count !== 1 ? 's' : ''} deleted`.padEnd(
|
||||||
|
maxCountLength,
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
`${chalk.green(pattern.padEnd(maxPatternLength))} ${chalk.red(itemCount)} ${chalk.yellow(formatSize(deletedCounts[pattern].size).padStart(maxSizeLength))}`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Calculate total deleted items and size
|
||||||
|
console.log(
|
||||||
|
chalk.magenta(
|
||||||
|
`Total deleted items: ${Object.values(deletedCounts).reduce((acc, { count }) => acc + count, 0)}`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
console.log(chalk.cyan(`Total size of deleted items: ${formatSize(totalSize)}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get patterns from command-line arguments
|
||||||
|
const patterns = process.argv.slice(2)
|
||||||
|
|
||||||
|
if (patterns.length > 0) {
|
||||||
|
void cleanDirectories(patterns)
|
||||||
|
} else {
|
||||||
|
console.log(chalk.red('No patterns provided. Usage: node script.js [patterns]'))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user