1- import { register , RegisterOptions , Service } from './index' ;
1+ import { register , RegisterOptions , Service , TSError } from './index' ;
22import { parse as parseUrl , format as formatUrl , UrlWithStringQuery , fileURLToPath , pathToFileURL } from 'url' ;
33import { extname , resolve as pathResolve } from 'path' ;
44import * as assert from 'assert' ;
@@ -101,7 +101,12 @@ export function filterHooksByAPIVersion(
101101/** @internal */
102102export function registerAndCreateEsmHooks ( opts ?: RegisterOptions ) {
103103 // Automatically performs registration just like `-r ts-node/register`
104- const tsNodeInstance = register ( opts ) ;
104+ let tsNodeInstance : Service ;
105+ try {
106+ tsNodeInstance = register ( opts ) ;
107+ } catch ( error ) {
108+ throw makeSerializableLoaderError ( error ) ;
109+ }
105110
106111 return createEsmHooks ( tsNodeInstance ) ;
107112}
@@ -113,10 +118,10 @@ export function createEsmHooks(tsNodeService: Service) {
113118 const extensions = tsNodeService . extensions ;
114119
115120 const hooksAPI = filterHooksByAPIVersion ( {
116- resolve,
117- load,
118- getFormat,
119- transformSource,
121+ resolve : wrapHook ( resolve ) ,
122+ load : wrapHook ( load ) ,
123+ getFormat : wrapHook ( getFormat ) ,
124+ transformSource : wrapHook ( transformSource ) ,
120125 } ) ;
121126
122127 function isFileUrlOrNodeStyleSpecifier ( parsed : UrlWithStringQuery ) {
@@ -356,3 +361,48 @@ async function addShortCircuitFlag<T>(fn: () => Promise<T>) {
356361 shortCircuit : true ,
357362 } ;
358363}
364+
365+ function wrapHook < T extends ( ...args : any [ ] ) => Promise < any > > ( hook : T ) : T {
366+ return ( async ( ...args : Parameters < T > ) => {
367+ try {
368+ return await hook ( ...args ) ;
369+ } catch ( error ) {
370+ throw makeSerializableLoaderError ( error ) ;
371+ }
372+ } ) as T ;
373+ }
374+
375+ function makeSerializableLoaderError ( error : unknown ) {
376+ if ( error instanceof TSError || isTSError ( error ) ) {
377+ const serializable = new Error ( error . message ) ;
378+ serializable . name = error . name ;
379+ if ( typeof error . stack === 'string' ) {
380+ serializable . stack = error . stack ;
381+ }
382+ Object . defineProperty ( serializable , 'diagnosticText' , {
383+ configurable : true ,
384+ enumerable : true ,
385+ writable : true ,
386+ value : error . diagnosticText ,
387+ } ) ;
388+ Object . defineProperty ( serializable , 'diagnosticCodes' , {
389+ configurable : true ,
390+ enumerable : true ,
391+ writable : true ,
392+ value : error . diagnosticCodes ,
393+ } ) ;
394+ return serializable ;
395+ }
396+ return error ;
397+ }
398+
399+ function isTSError ( error : unknown ) : error is TSError {
400+ return (
401+ typeof error === 'object' &&
402+ error !== null &&
403+ ( error as TSError ) . name === 'TSError' &&
404+ typeof ( error as TSError ) . message === 'string' &&
405+ typeof ( error as TSError ) . diagnosticText === 'string' &&
406+ Array . isArray ( ( error as TSError ) . diagnosticCodes )
407+ ) ;
408+ }
0 commit comments