11import { parseJSON5 , parseJSONC , parseTOML , type JSONCParseError } from 'confbox' ;
22import { pklLoader } from 'cosmiconfig-loader-pkl' ;
33import { createJiti } from 'jiti' ;
4+ import path from 'path' ;
45
56/** Matches cosmiconfig's `Loader` signature, which may also be synchronous. */
67type Loader = ( filePath : string , content : string ) => object | null | Promise < object | null > ;
@@ -81,7 +82,7 @@ function describe(error: JSONCParseError, content: string): string {
8182 */
8283const jiti = createJiti ( '' , { interopDefault : true , moduleCache : false , fsCache : false } ) ;
8384
84- const loaders : Record < 'javascript' | 'json5' | 'jsonc' | 'pkl' | 'toml' | 'typescript ' , Loader > = {
85+ const loaders : Record < 'javascript' | 'json5' | 'jsonc' | 'pkl' | 'toml' | 'transpiled ' , Loader > = {
8586 // Must be `require`, and must not be `import()`.
8687 //
8788 // Package code runs in Pulsar's *renderer* process, where a dynamic `import()`
@@ -166,10 +167,11 @@ const loaders: Record<'javascript' | 'json5' | 'jsonc' | 'pkl' | 'toml' | 'types
166167 }
167168 } ,
168169
169- // TypeScript, and any build file written as an ES module. Neither `require`
170- // nor cosmiconfig's `loadJs` can read these: `loadJs` does no type stripping
171- // at all, so it falls back to `require`, which reads the source as CommonJS
172- // JavaScript and reports `Unexpected token 'export'`.
170+ // Everything `require` cannot read, whether because of type annotations
171+ // (`.ts`, `.mts`, `.cts`) or ESM syntax (`.mjs`, and the TypeScript ones
172+ // again). cosmiconfig's `loadJs` cannot read them either: it does no type
173+ // stripping at all, so it falls back to `require`, which parses the source as
174+ // CommonJS JavaScript and reports `Unexpected token 'export'`.
173175 //
174176 // jiti transpiles and evaluates in-process, which also means the dynamic
175177 // `import()` described on the `javascript` loader is never reached. That is
@@ -178,11 +180,15 @@ const loaders: Record<'javascript' | 'json5' | 'jsonc' | 'pkl' | 'toml' | 'types
178180 // down is not an error anyone gets to see. jiti marks the synchronous call
179181 // deprecated in favour of `jiti.import()` "for better compatibility"; here
180182 // that trade runs the wrong way, so the deprecation is accepted knowingly.
181- typescript ( filePath : string ) {
183+ //
184+ // The format in the error message follows the extension rather than the
185+ // loader: a failed `.mjs` is a JavaScript error, and saying otherwise would
186+ // point the reader at a language their build file is not written in.
187+ transpiled ( filePath : string ) {
182188 try {
183189 return unwrapDefault ( jiti ( filePath ) as Record < string , unknown > | null ) ;
184190 } catch ( error ) {
185- rethrow ( 'TypeScript' , filePath , error ) ;
191+ rethrow ( path . extname ( filePath ) . endsWith ( 'js' ) ? 'JavaScript' : 'TypeScript' , filePath , error ) ;
186192 }
187193 }
188194} ;
0 commit comments