@@ -3,6 +3,51 @@ import fs from "node:fs/promises";
33import os from "node:os" ;
44import path from "node:path" ;
55
6+ const asyncPrefixRoots = new Map < string , string > ( ) ;
7+ const pendingAsyncPrefixRoots = new Map < string , Promise < string > > ( ) ;
8+ const syncPrefixRoots = new Map < string , string > ( ) ;
9+ let nextAsyncDirIndex = 0 ;
10+ let nextSyncDirIndex = 0 ;
11+
12+ function getRootKey ( options : { prefix : string ; parentDir ?: string } ) : string {
13+ return `${ options . parentDir ?? os . tmpdir ( ) } \u0000${ options . prefix } ` ;
14+ }
15+
16+ async function ensureAsyncPrefixRoot ( options : {
17+ prefix : string ;
18+ parentDir ?: string ;
19+ } ) : Promise < string > {
20+ const key = getRootKey ( options ) ;
21+ const cached = asyncPrefixRoots . get ( key ) ;
22+ if ( cached ) {
23+ return cached ;
24+ }
25+ const pending = pendingAsyncPrefixRoots . get ( key ) ;
26+ if ( pending ) {
27+ return await pending ;
28+ }
29+ const create = fs . mkdtemp ( path . join ( options . parentDir ?? os . tmpdir ( ) , options . prefix ) ) ;
30+ pendingAsyncPrefixRoots . set ( key , create ) ;
31+ try {
32+ const root = await create ;
33+ asyncPrefixRoots . set ( key , root ) ;
34+ return root ;
35+ } finally {
36+ pendingAsyncPrefixRoots . delete ( key ) ;
37+ }
38+ }
39+
40+ function ensureSyncPrefixRoot ( options : { prefix : string ; parentDir ?: string } ) : string {
41+ const key = getRootKey ( options ) ;
42+ const cached = syncPrefixRoots . get ( key ) ;
43+ if ( cached ) {
44+ return cached ;
45+ }
46+ const root = fsSync . mkdtempSync ( path . join ( options . parentDir ?? os . tmpdir ( ) , options . prefix ) ) ;
47+ syncPrefixRoots . set ( key , root ) ;
48+ return root ;
49+ }
50+
651export async function withTempDir < T > (
752 options : {
853 prefix : string ;
@@ -11,7 +56,10 @@ export async function withTempDir<T>(
1156 } ,
1257 run : ( dir : string ) => Promise < T > ,
1358) : Promise < T > {
14- const base = await fs . mkdtemp ( path . join ( options . parentDir ?? os . tmpdir ( ) , options . prefix ) ) ;
59+ const root = await ensureAsyncPrefixRoot ( options ) ;
60+ const base = path . join ( root , `dir-${ String ( nextAsyncDirIndex ) } ` ) ;
61+ nextAsyncDirIndex += 1 ;
62+ await fs . mkdir ( base , { recursive : true } ) ;
1563 const dir = options . subdir ? path . join ( base , options . subdir ) : base ;
1664 if ( options . subdir ) {
1765 await fs . mkdir ( dir , { recursive : true } ) ;
@@ -68,7 +116,10 @@ export function withTempDirSync<T>(
68116 } ,
69117 run : ( dir : string ) => T ,
70118) : T {
71- const base = fsSync . mkdtempSync ( path . join ( options . parentDir ?? os . tmpdir ( ) , options . prefix ) ) ;
119+ const root = ensureSyncPrefixRoot ( options ) ;
120+ const base = path . join ( root , `dir-${ String ( nextSyncDirIndex ) } ` ) ;
121+ nextSyncDirIndex += 1 ;
122+ fsSync . mkdirSync ( base , { recursive : true } ) ;
72123 const dir = options . subdir ? path . join ( base , options . subdir ) : base ;
73124 if ( options . subdir ) {
74125 fsSync . mkdirSync ( dir , { recursive : true } ) ;
0 commit comments