Remove tempy dependency, use Node builtins for temp directories#7180
Remove tempy dependency, use Node builtins for temp directories#7180ryancbahan merged 1 commit intomainfrom
Conversation
71ffc89 to
cd57cb2
Compare
|
We detected some changes at Caution DO NOT create changesets for features which you do not wish to be included in the public changelog of the next CLI release. |
cd57cb2 to
85b975c
Compare
5197bd1 to
7f65ad2
Compare
85b975c to
bfd7342
Compare
Replace tempy with Node's built-in fs.mkdtemp/mkdtempSync for temp
directory creation and cleanup. Add a small temp-dir.ts module that
captures the real temp directory path at module load time using async
realpath (via top-level await), which resolves both macOS symlinks
(/var -> /private/var) and Windows 8.3 short names (RUNNER~1 ->
runneradmin). Cleanup uses maxRetries: 2 for Windows robustness.
All matching tempy's behavior.
Fix three test files that used bare vi.mock('os') to use partial mocks
instead, preserving real os.tmpdir() while still allowing specific
function mocking (platform, hostname, EOL).
Also removes unused tempy dep from e2e and workspace packages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7f65ad2 to
f0708ae
Compare
bfd7342 to
73a9304
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationspackages/cli-kit/dist/private/node/temp-dir.d.tsexport declare const systemTempDir: string;
Existing type declarationspackages/cli-kit/dist/public/node/path.d.ts import type { URL } from 'url';
/**
* Joins a list of paths together.
*
* @param paths - Paths to join.
* @returns Joined path.
*/
export declare function joinPath(...paths: string[]): string;
/**
* Normalizes a path.
*
* @param path - Path to normalize.
* @returns Normalized path.
*/
export declare function normalizePath(path: string): string;
/**
* Resolves a list of paths together.
*
* @param paths - Paths to resolve.
* @returns Resolved path.
*/
export declare function resolvePath(...paths: string[]): string;
/**
* Returns the relative path from one path to another.
*
* @param from - Path to resolve from.
* @param to - Path to resolve to.
* @returns Relative path.
*/
export declare function relativePath(from: string, to: string): string;
/**
* Returns whether the path is absolute.
*
* @param path - Path to check.
* @returns Whether the path is absolute.
*/
export declare function isAbsolutePath(path: string): boolean;
/**
* Returns the directory name of a path.
*
* @param path - Path to get the directory name of.
* @returns Directory name.
*/
export declare function dirname(path: string): string;
/**
* Returns the base name of a path.
*
* @param path - Path to get the base name of.
* @param ext - Optional extension to remove from the result.
* @returns Base name.
*/
export declare function basename(path: string, ext?: string): string;
/**
* Returns the extension of the path.
*
* @param path - Path to get the extension of.
* @returns Extension.
*/
export declare function extname(path: string): string;
/**
* Parses a path into its components (root, dir, base, ext, name).
*
* @param path - Path to parse.
* @returns Parsed path object.
*/
export declare function parsePath(path: string): {
root: string;
dir: string;
base: string;
ext: string;
name: string;
};
/**
+ * Returns the longest common parent directory of two absolute paths.
+ *
+ * @param first - First absolute path.
+ * @param second - Second absolute path.
+ * @returns The common parent directory, or '/' if they share only the root.
+ */
+export declare function commonParentDirectory(first: string, second: string): string;
+/**
* Given an absolute filesystem path, it makes it relative to
* the current working directory. This is useful when logging paths
* to allow the users to click on the file and let the OS open it
* in the editor of choice.
*
* @param path - Path to relativize.
* @param dir - Current working directory.
* @returns Relativized path.
*/
export declare function relativizePath(path: string, dir?: string): string;
/**
* Given 2 paths, it returns whether the second path is a subpath of the first path.
*
* @param mainPath - The main path.
* @param subpath - The subpath.
* @returns Whether the subpath is a subpath of the main path.
*/
export declare function isSubpath(mainPath: string, subpath: string): boolean;
/**
* Given a module's import.meta.url it returns the directory containing the module.
*
* @param moduleURL - The value of import.meta.url in the context of the caller module.
* @returns The path to the directory containing the caller module.
*/
export declare function moduleDirectory(moduleURL: string | URL): string;
/**
* When running a script using `npm run`, something interesting happens. If the current
* folder does not have a `package.json` or a `node_modules` folder, npm will traverse
* the directory tree upwards until it finds one. Then it will run the script and set
* `process.cwd()` to that folder, while the actual path is stored in the INIT_CWD
* environment variable (see here: https://docs.npmjs.com/cli/v9/commands/npm-run-script#description).
*
* @returns The path to the current working directory.
*/
export declare function cwd(): string;
/**
* Tries to get the value of the `--path` argument, if provided.
*
* @param argv - The arguments to search for the `--path` argument.
* @returns The value of the `--path` argument, if provided.
*/
export declare function sniffForPath(argv?: string[]): string | undefined;
/**
* Returns whether the `--json` or `-j` flags are present in the arguments.
*
* @param argv - The arguments to search for the `--json` and `-j` flags.
* @returns Whether the `--json` or `-j` flag is present in the arguments.
*/
export declare function sniffForJson(argv?: string[]): boolean;
/**
* Removes any `..` traversal segments from a relative path and calls `warn`
* if any were stripped. Normal `..` that cancel out within the path (e.g.
* `foo/../bar` → `bar`) are collapsed but never allowed to escape the root.
* Both `/` and `\` are treated as separators for cross-platform safety.
*
* @param input - The relative path to sanitize.
* @param warn - Called with a human-readable warning when traversal segments are removed.
* @returns The sanitized path (may be an empty string if all segments were traversal).
*/
export declare function sanitizeRelativePath(input: string, warn: (msg: string) => void): string;
|
dmerand
left a comment
There was a problem hiding this comment.
This looks reasonable to me. I checked tempy’s implementation, and the new mkdtemp / rm flow effectively matches what temporaryDirectory() / temporaryDirectoryTask() were doing.
Only small consistency nit: since this PR introduces systemTempDir specifically to preserve tempy’s resolved-temp-directory semantics, it might be worth having mkTmpDir() use the same base as well instead of raw os.tmpdir(). Not a blocker.

Summary
tempywith Node's built-infs.mkdtemp/mkdtempSyncfor temp directory creation and cleanuptemp-dir.tsmodule that captures the real temp directory at module load time (withrealpathSyncto resolve macOS symlinks), matching tempy'stemp-dirpackage approachmaxRetries: 2for Windows robustness, matching tempy's behaviorfs.test.ts,npm.test.ts,generate-theme-name.test.ts) that used barevi.mock('os')— converted to partial mocks that preserveos.tmpdir()while still allowing specific function mockingtempyfrom cli-kit, e2e (unused), and workspace packagesworkspace/src/type-diff.jsto use inlinemkdtemp/rm