Files
notesnook/apps/mobile/scripts/clean.mjs
Abdullah Atta 3de225f7c9 mobile: upgrade react native 0.82
this commit also bump app version to 3.3.10-beta.0
2025-11-27 11:32:50 +05:00

163 lines
4.1 KiB
JavaScript

import { promises as fs } from "fs";
import path from "path";
import os from "os";
import { exec } from "child_process";
import readline from "readline";
const PROJECT_ROOT = path.resolve(
new URL(import.meta.url).pathname,
"..",
".."
); // scripts/.. -> mobile
const args = process.argv.slice(2);
const FLAGS = {
yes: args.includes("-y") || args.includes("--yes"),
dryRun: args.includes("--dry-run"),
all: args.includes("--all"),
verbose: args.includes("-v") || args.includes("--verbose")
};
const DEFAULT_TARGETS = [
"node_modules",
"android/build",
"android/app/build",
"ios/Pods",
"ios/DerivedData" // sometimes used as DerivedData path
];
const EXTRA_TARGETS = [
"android/.gradle",
".gradle",
"ios/build",
"ios/Podfile.lock",
"ios/xcuserdata",
".expo",
".expo-shared",
".vscode",
"build",
".idea"
];
const targets = new Set([
...DEFAULT_TARGETS,
...(FLAGS.all ? EXTRA_TARGETS : [])
]);
function resolveTargets(root) {
return [...targets].map((t) => ({ rel: t, abs: path.resolve(root, t) }));
}
async function pathExists(p) {
try {
await fs.access(p);
return true;
} catch {
return false;
}
}
function execPromise(cmd) {
return new Promise((res, rej) => {
exec(cmd, { maxBuffer: 1024 * 1024 * 10 }, (err, stdout, stderr) => {
if (err) return rej({ err, stdout, stderr });
res({ stdout, stderr });
});
});
}
async function removeWithNode(p) {
// fs.rm is available in Node 14.14+; fallback to rmdir if necessary
if (fs.rm) {
await fs.rm(p, { recursive: true, force: true });
} else if (fs.rmdir) {
// rmdir with recursive option deprecated in some nodes but try
await fs.rmdir(p, { recursive: true });
} else {
throw new Error("No supported fs remove method found");
}
}
async function removePath(p) {
if (FLAGS.verbose) console.log("Removing:", p);
try {
// Prefer Node API
await removeWithNode(p);
return { ok: true };
} catch (nodeErr) {
// Fallback to shell command
const isWin = os.platform() === "win32";
const cmd = isWin ? `rd /s /q "${p}"` : `rm -rf "${p}"`;
try {
await execPromise(cmd);
return { ok: true, fallback: true };
} catch (shellErr) {
return { ok: false, error: shellErr };
}
}
}
async function confirmPrompt(message) {
if (FLAGS.yes) return true;
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const answer = await new Promise((res) =>
rl.question(`${message} (y/N): `, (ans) => {
rl.close();
res(ans);
})
);
return /^y(es)?$/i.test(answer.trim());
}
async function run() {
console.log("Project root:", PROJECT_ROOT);
const resolved = resolveTargets(PROJECT_ROOT);
const existing = [];
for (const t of resolved) {
if (await pathExists(t.abs)) existing.push(t);
}
if (existing.length === 0) {
console.log("No matching targets found. Nothing to do.");
return;
}
console.log("Will remove the following paths:");
for (const e of existing) console.log(" -", e.rel);
if (FLAGS.dryRun) {
console.log("\nDry-run mode enabled. No files will be removed.");
return;
}
const ok = await confirmPrompt("Proceed to delete the listed paths?");
if (!ok) {
console.log("Aborted by user.");
return;
}
const results = [];
for (const e of existing) {
try {
const res = await removePath(e.abs);
results.push({ target: e.rel, success: res.ok, info: res });
console.log(res.ok ? `Deleted: ${e.rel}` : `Failed: ${e.rel}`);
} catch (err) {
results.push({ target: e.rel, success: false, info: err });
console.log(`Failed: ${e.rel}${err?.message || err}`);
}
}
const deleted = results.filter((r) => r.success).length;
const failed = results.length - deleted;
console.log(`\nSummary: ${deleted} deleted, ${failed} failed.`);
if (failed > 0) {
console.log("Failed items:");
for (const f of results.filter((r) => !r.success))
console.log(" -", f.target);
}
console.log("Done.");
}
run().catch((err) => {
console.error("Unexpected error:", err);
process.exitCode = 1;
});