11import path from 'node:path'
22import { builtinModules } from 'node:module'
3- import { existsSync , promises as fs , statSync } from 'node:fs'
4- import { fileURLToPath } from 'node:url'
3+ import { promises as fs } from 'node:fs'
54
65import { parseSync , Visitor } from 'oxc-parser'
76import type {
@@ -10,15 +9,16 @@ import type {
109 ImportExpression ,
1110 TSImportEqualsDeclaration ,
1211} from 'oxc-parser'
13- import {
14- ResolverFactory ,
15- type NapiResolveOptions ,
16- type TsconfigOptions as ResolverTsconfigOptions ,
17- } from 'oxc-resolver'
1812import { createMatchPath } from 'tsconfig-paths'
1913import { getTsconfig } from 'get-tsconfig'
2014
2115import type { CssResolver } from './types.js'
16+ import {
17+ createResolverFactory ,
18+ findExistingFile ,
19+ normalizeResolverResult ,
20+ resolveWithFactory ,
21+ } from './moduleResolution.js'
2222
2323const SCRIPT_EXTENSIONS = [ '.ts' , '.tsx' , '.mts' , '.cts' , '.js' , '.jsx' , '.mjs' , '.cjs' ]
2424
@@ -84,7 +84,10 @@ export async function collectStyleImports(
8484 cwd ,
8585 resolutionExtensions ,
8686 scriptExtensions ,
87- graphOptions ,
87+ {
88+ conditions : graphOptions ?. conditions ,
89+ tsconfig : graphOptions ?. tsConfig ,
90+ } ,
8891 )
8992
9093 async function walk ( filePath : string ) : Promise < void > {
@@ -496,103 +499,6 @@ function unwrapExpression(expression: Expression): Expression {
496499 return expression
497500}
498501
499- function normalizeResolverResult (
500- result : string | undefined ,
501- cwd : string ,
502- ) : string | undefined {
503- if ( ! result ) {
504- return undefined
505- }
506- if ( result . startsWith ( 'file://' ) ) {
507- try {
508- return fileURLToPath ( new URL ( result ) )
509- } catch {
510- return undefined
511- }
512- }
513- return path . isAbsolute ( result ) ? result : path . resolve ( cwd , result )
514- }
515-
516- function resolveWithFactory (
517- factory : ResolverFactory ,
518- specifier : string ,
519- importer : string ,
520- extensions : string [ ] ,
521- ) : string | undefined {
522- if ( specifier . startsWith ( 'file://' ) ) {
523- try {
524- return findExistingFile ( fileURLToPath ( new URL ( specifier ) ) , extensions )
525- } catch {
526- return undefined
527- }
528- }
529- if ( / ^ [ a - z ] [ \w + . - ] * : / i. test ( specifier ) ) {
530- return undefined
531- }
532- try {
533- const result = factory . resolveFileSync ( importer , specifier )
534- return result ?. path
535- } catch {
536- return undefined
537- }
538- }
539-
540- function createResolverFactory (
541- cwd : string ,
542- extensions : string [ ] ,
543- scriptExtensions : string [ ] ,
544- graphOptions ?: ModuleGraphOptions ,
545- ) : ResolverFactory {
546- const options : NapiResolveOptions = {
547- extensions,
548- conditionNames : graphOptions ?. conditions ,
549- }
550- const extensionAlias = buildExtensionAlias ( scriptExtensions )
551- if ( extensionAlias ) {
552- options . extensionAlias = extensionAlias
553- }
554- const tsconfigOption = resolveResolverTsconfig ( graphOptions ?. tsConfig , cwd )
555- options . tsconfig = tsconfigOption ?? 'auto'
556- return new ResolverFactory ( options )
557- }
558-
559- function buildExtensionAlias (
560- scriptExtensions : string [ ] ,
561- ) : Record < string , string [ ] > | undefined {
562- const alias : Record < string , string [ ] > = { }
563- const jsTargets = dedupeExtensions (
564- scriptExtensions . filter ( ext =>
565- [ '.js' , '.ts' , '.tsx' , '.mjs' , '.cjs' , '.mts' , '.cts' ] . includes ( ext ) ,
566- ) ,
567- )
568- if ( jsTargets . length > 0 ) {
569- for ( const key of [ '.js' , '.mjs' , '.cjs' ] ) {
570- alias [ key ] = jsTargets
571- }
572- }
573- const jsxTargets = dedupeExtensions (
574- scriptExtensions . filter ( ext => ext === '.jsx' || ext === '.tsx' ) ,
575- )
576- if ( jsxTargets . length > 0 ) {
577- alias [ '.jsx' ] = jsxTargets
578- }
579- return Object . keys ( alias ) . length > 0 ? alias : undefined
580- }
581-
582- function resolveResolverTsconfig (
583- input : TsconfigLike | undefined ,
584- cwd : string ,
585- ) : ResolverTsconfigOptions | undefined {
586- if ( ! input || typeof input !== 'string' ) {
587- return undefined
588- }
589- const resolved = resolveTsconfigPath ( input , cwd )
590- if ( ! resolved ) {
591- return undefined
592- }
593- return { configFile : resolved }
594- }
595-
596502function createTsconfigMatcher (
597503 input : TsconfigLike | undefined ,
598504 cwd : string ,
@@ -674,46 +580,3 @@ function normalizeTsconfigCompilerOptions(
674580 : path . resolve ( configDir , compilerOptions . baseUrl )
675581 return { absoluteBaseUrl, paths : normalizedPaths }
676582}
677-
678- function resolveTsconfigPath ( tsconfigPath : string , cwd : string ) : string | undefined {
679- const absolute = path . isAbsolute ( tsconfigPath )
680- ? tsconfigPath
681- : path . resolve ( cwd , tsconfigPath )
682- if ( ! existsSync ( absolute ) ) {
683- return undefined
684- }
685- const stats = statSync ( absolute )
686- if ( stats . isDirectory ( ) ) {
687- const candidate = path . join ( absolute , 'tsconfig.json' )
688- return existsSync ( candidate ) ? candidate : undefined
689- }
690- return absolute
691- }
692-
693- function findExistingFile ( candidate : string , extensions : string [ ] ) : string | undefined {
694- const candidateHasExt = hasExtension ( candidate )
695- if ( candidateHasExt && existsSync ( candidate ) ) {
696- return candidate
697- }
698- if ( ! candidateHasExt ) {
699- for ( const ext of extensions ) {
700- const withExt = `${ candidate } ${ ext } `
701- if ( existsSync ( withExt ) ) {
702- return withExt
703- }
704- }
705- }
706- if ( existsSync ( candidate ) && statSync ( candidate ) . isDirectory ( ) ) {
707- for ( const ext of extensions ) {
708- const indexPath = path . join ( candidate , `index${ ext } ` )
709- if ( existsSync ( indexPath ) ) {
710- return indexPath
711- }
712- }
713- }
714- return undefined
715- }
716-
717- function hasExtension ( filePath : string ) : boolean {
718- return Boolean ( path . extname ( filePath ) )
719- }
0 commit comments