@vltpkg/rollback-remove
Advanced tools
| export declare class RollbackRemove { | ||
| #private; | ||
| rm(path: string): Promise<void>; | ||
| confirm(): void; | ||
| rollback(): Promise<void>; | ||
| } |
| import { spawn } from 'node:child_process'; | ||
| import { rename } from 'node:fs/promises'; | ||
| import { basename, dirname } from 'node:path'; | ||
| import { rimraf } from 'rimraf'; | ||
| import { __CODE_SPLIT_SCRIPT_NAME } from "./remove.js"; | ||
| const isDeno = globalThis.Deno != undefined; | ||
| export class RollbackRemove { | ||
| #key = String(Math.random()).substring(2); | ||
| #paths = new Map(); | ||
| async rm(path) { | ||
| if (this.#paths.has(path)) | ||
| return; | ||
| const target = `${dirname(path)}/.VLT.DELETE.${this.#key}.${basename(path)}`; | ||
| this.#paths.set(path, target); | ||
| await rename(path, target).catch((e) => { | ||
| if (e instanceof Error && | ||
| 'code' in e && | ||
| /* c8 ignore start - very spurious weirdness on Windows */ | ||
| (e.code === 'ENOENT' || e.code === 'EPERM') | ||
| /* c8 ignore stop */ | ||
| ) { | ||
| this.#paths.delete(path); | ||
| return; | ||
| } | ||
| /* c8 ignore next */ | ||
| throw e; | ||
| }); | ||
| } | ||
| confirm() { | ||
| // nothing to confirm! | ||
| if (!this.#paths.size) | ||
| return; | ||
| const env = { ...process.env }; | ||
| const args = []; | ||
| // Deno on Windows does not support detached processes | ||
| // https://github.com/denoland/deno/issues/25867 | ||
| // TODO: figure out something better to do here? | ||
| const detached = !(isDeno && process.platform === 'win32'); | ||
| // If we are running deno from source we need to add the | ||
| // unstable flags we need. The '-A' flag does not need | ||
| // to be passed in as Deno supplies that automatically. | ||
| if (isDeno) { | ||
| args.push('--unstable-node-globals', '--unstable-bare-node-builtins'); | ||
| } | ||
| args.push(__CODE_SPLIT_SCRIPT_NAME); | ||
| const child = spawn(process.execPath, args, { | ||
| stdio: ['pipe', 'ignore', 'ignore'], | ||
| detached, | ||
| env, | ||
| }); | ||
| for (const path of this.#paths.values()) { | ||
| child.stdin.write(`${path}\0`); | ||
| } | ||
| child.stdin.end(); | ||
| if (detached) { | ||
| child.unref(); | ||
| } | ||
| this.#paths.clear(); | ||
| } | ||
| async rollback() { | ||
| const promises = []; | ||
| for (const [original, moved] of this.#paths) { | ||
| promises.push(rimraf(original) | ||
| /* c8 ignore next */ | ||
| .catch(() => { }) | ||
| .then(() => rename(moved, original))); | ||
| } | ||
| await Promise.all(promises); | ||
| this.#paths.clear(); | ||
| } | ||
| } |
| export declare const __CODE_SPLIT_SCRIPT_NAME: string; |
| import { pathToFileURL } from 'node:url'; | ||
| import { rimraf } from 'rimraf'; | ||
| export const __CODE_SPLIT_SCRIPT_NAME = import.meta.filename; | ||
| const isMain = (path) => path === __CODE_SPLIT_SCRIPT_NAME || | ||
| path === pathToFileURL(__CODE_SPLIT_SCRIPT_NAME).toString(); | ||
| // This is run as a background process, and all the paths to | ||
| // be removed written into stdin. We can't pass on argv, because | ||
| // it'll be a very long list in many cases. | ||
| const main = async () => { | ||
| const paths = await new Promise(res => { | ||
| const chunks = []; | ||
| let chunkLen = 0; | ||
| process.stdin.on('data', chunk => { | ||
| chunks.push(chunk); | ||
| chunkLen += chunk.length; | ||
| }); | ||
| process.stdin.on('end', () => { | ||
| res(Buffer.concat(chunks, chunkLen) | ||
| .toString() | ||
| .split('\0') | ||
| .filter(i => !!i)); | ||
| }); | ||
| }); | ||
| if (paths.length) { | ||
| await rimraf(paths); | ||
| } | ||
| }; | ||
| if (isMain(process.argv[1])) { | ||
| await main(); | ||
| } |
+1
-1
| { | ||
| "name": "@vltpkg/rollback-remove", | ||
| "description": "Mark paths as removed, then remove them or roll back", | ||
| "version": "1.0.0-rc.23", | ||
| "version": "1.0.0-rc.24", | ||
| "repository": { | ||
@@ -6,0 +6,0 @@ "type": "git", |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
8503
77.92%7
133.33%108
Infinity%0
-100%2
Infinity%