@@ -127,68 +127,82 @@ const supportedBuiltins = {
127127 browser : null , // Not available in browser
128128 node : async ( ) => {
129129 const runtime = typeof Bun !== 'undefined' ? 'Bun' : typeof Deno !== 'undefined' ? 'Deno' : 'Node.js' ;
130- if ( runtime !== 'Node.js' ) {
131- console . log ( `[${ runtime } ] Loading fs/promises via builtin resolver` ) ;
132- }
133- try {
134- const m = await import ( 'node:fs/promises' ) ;
135- // Debug: Log what we got (only in non-Node environments for debugging)
136- const runtime = typeof Bun !== 'undefined' ? 'Bun' : typeof Deno !== 'undefined' ? 'Deno' : 'Node.js' ;
137- if ( runtime !== 'Node.js' ) {
138- console . log ( `[${ runtime } ] fs/promises mkdir.length:` , m . mkdir ?. length ) ;
139- }
140-
141- // Validate that we got promise-based functions, not callback-based ones
142- if ( m . mkdir && m . mkdir . length === 3 ) {
143- console . log ( `[${ runtime } ] Detected callback-based functions, using promisify fallback` ) ;
144- // This means we got callback-based fs.mkdir instead of promise-based fs/promises.mkdir
145- // This can happen in some runtime environments where node:fs/promises isn't properly implemented
146- // Fall back to creating promise-based versions using util.promisify
130+
131+ // For Bun and Deno, use a different approach since their node:fs/promises may not be fully compatible
132+ if ( runtime === 'Bun' || runtime === 'Deno' ) {
133+ console . log ( `[${ runtime } ] Using promisify fallback for fs/promises compatibility` ) ;
134+ try {
147135 const fs = await import ( 'node:fs' ) ;
148136 const { promisify } = await import ( 'node:util' ) ;
149137
150- // Create promise-based versions of the main fs functions
138+ // Create wrapper functions that match native fs/promises signatures
139+ // These need to have the correct .length property and be async functions
140+ const createAsyncWrapper = ( promisifiedFn , expectedLength ) => {
141+ // Create an async function with the correct length
142+ const wrapper = {
143+ 1 : async ( a ) => promisifiedFn ( a ) ,
144+ 2 : async ( a , b ) => promisifiedFn ( a , b ) ,
145+ 3 : async ( a , b , c ) => promisifiedFn ( a , b , c ) ,
146+ 4 : async ( a , b , c , d ) => promisifiedFn ( a , b , c , d )
147+ } [ expectedLength ] ;
148+
149+ // Copy the name if possible
150+ try {
151+ Object . defineProperty ( wrapper , 'name' , { value : promisifiedFn . name } ) ;
152+ } catch ( e ) {
153+ // Ignore if name can't be set
154+ }
155+
156+ return wrapper || promisifiedFn ;
157+ } ;
158+
151159 const promisifiedFs = {
152- access : promisify ( fs . access ) ,
153- appendFile : promisify ( fs . appendFile ) ,
154- chmod : promisify ( fs . chmod ) ,
155- chown : promisify ( fs . chown ) ,
156- copyFile : promisify ( fs . copyFile ) ,
157- lchmod : promisify ( fs . lchmod ) ,
158- lchown : promisify ( fs . lchown ) ,
159- link : promisify ( fs . link ) ,
160- lstat : promisify ( fs . lstat ) ,
161- mkdir : promisify ( fs . mkdir ) ,
162- mkdtemp : promisify ( fs . mkdtemp ) ,
163- open : promisify ( fs . open ) ,
164- readdir : promisify ( fs . readdir ) ,
165- readFile : promisify ( fs . readFile ) ,
166- readlink : promisify ( fs . readlink ) ,
167- realpath : promisify ( fs . realpath ) ,
168- rename : promisify ( fs . rename ) ,
169- rmdir : promisify ( fs . rmdir ) ,
170- stat : promisify ( fs . stat ) ,
171- symlink : promisify ( fs . symlink ) ,
172- truncate : promisify ( fs . truncate ) ,
173- unlink : promisify ( fs . unlink ) ,
174- utimes : promisify ( fs . utimes ) ,
175- writeFile : promisify ( fs . writeFile ) ,
160+ access : createAsyncWrapper ( promisify ( fs . access ) , 2 ) ,
161+ appendFile : createAsyncWrapper ( promisify ( fs . appendFile ) , 3 ) ,
162+ chmod : createAsyncWrapper ( promisify ( fs . chmod ) , 2 ) ,
163+ chown : createAsyncWrapper ( promisify ( fs . chown ) , 3 ) ,
164+ copyFile : createAsyncWrapper ( promisify ( fs . copyFile ) , 3 ) ,
165+ lchmod : createAsyncWrapper ( promisify ( fs . lchmod ) , 2 ) ,
166+ lchown : createAsyncWrapper ( promisify ( fs . lchown ) , 3 ) ,
167+ link : createAsyncWrapper ( promisify ( fs . link ) , 2 ) ,
168+ lstat : createAsyncWrapper ( promisify ( fs . lstat ) , 2 ) ,
169+ mkdir : createAsyncWrapper ( promisify ( fs . mkdir ) , 2 ) ,
170+ mkdtemp : createAsyncWrapper ( promisify ( fs . mkdtemp ) , 2 ) ,
171+ open : createAsyncWrapper ( promisify ( fs . open ) , 3 ) ,
172+ readdir : createAsyncWrapper ( promisify ( fs . readdir ) , 2 ) ,
173+ readFile : createAsyncWrapper ( promisify ( fs . readFile ) , 2 ) ,
174+ readlink : createAsyncWrapper ( promisify ( fs . readlink ) , 2 ) ,
175+ realpath : createAsyncWrapper ( promisify ( fs . realpath ) , 2 ) ,
176+ rename : createAsyncWrapper ( promisify ( fs . rename ) , 2 ) ,
177+ rmdir : createAsyncWrapper ( promisify ( fs . rmdir ) , 2 ) ,
178+ stat : createAsyncWrapper ( promisify ( fs . stat ) , 2 ) ,
179+ symlink : createAsyncWrapper ( promisify ( fs . symlink ) , 3 ) ,
180+ truncate : createAsyncWrapper ( promisify ( fs . truncate ) , 2 ) ,
181+ unlink : createAsyncWrapper ( promisify ( fs . unlink ) , 1 ) ,
182+ utimes : createAsyncWrapper ( promisify ( fs . utimes ) , 3 ) ,
183+ writeFile : createAsyncWrapper ( promisify ( fs . writeFile ) , 3 ) ,
176184 constants : fs . constants
177185 } ;
178186
179187 // Add newer functions if they exist
180- if ( fs . rm ) promisifiedFs . rm = promisify ( fs . rm ) ;
181- if ( fs . cp ) promisifiedFs . cp = promisify ( fs . cp ) ;
182- if ( fs . lutimes ) promisifiedFs . lutimes = promisify ( fs . lutimes ) ;
183- if ( fs . opendir ) promisifiedFs . opendir = promisify ( fs . opendir ) ;
184- if ( fs . statfs ) promisifiedFs . statfs = promisify ( fs . statfs ) ;
188+ if ( fs . rm ) promisifiedFs . rm = createAsyncWrapper ( promisify ( fs . rm ) , 2 ) ;
189+ if ( fs . cp ) promisifiedFs . cp = createAsyncWrapper ( promisify ( fs . cp ) , 3 ) ;
190+ if ( fs . lutimes ) promisifiedFs . lutimes = createAsyncWrapper ( promisify ( fs . lutimes ) , 3 ) ;
191+ if ( fs . opendir ) promisifiedFs . opendir = createAsyncWrapper ( promisify ( fs . opendir ) , 2 ) ;
192+ if ( fs . statfs ) promisifiedFs . statfs = createAsyncWrapper ( promisify ( fs . statfs ) , 2 ) ;
185193 if ( fs . watch ) promisifiedFs . watch = fs . watch . bind ( fs ) ; // watch is not callback-based
186194
187- // Verify the fallback worked
188195 console . log ( `[${ runtime } ] Fallback mkdir.length:` , promisifiedFs . mkdir ?. length ) ;
189196 console . log ( `[${ runtime } ] Fallback mkdir.constructor.name:` , promisifiedFs . mkdir ?. constructor . name ) ;
190197 return { default : promisifiedFs , ...promisifiedFs } ;
198+ } catch ( error ) {
199+ throw new Error ( `Failed to create fs/promises fallback for ${ runtime } : ${ error . message } ` , { cause : error } ) ;
191200 }
201+ }
202+
203+ // For Node.js, use the native implementation
204+ try {
205+ const m = await import ( 'node:fs/promises' ) ;
192206 return { default : m , ...m } ;
193207 } catch ( error ) {
194208 throw new Error ( `Failed to load fs/promises module: ${ error . message } ` , { cause : error } ) ;
0 commit comments