@@ -69,12 +69,94 @@ function fileExists(filePath: string): boolean {
6969 }
7070}
7171
72- export function hasPackageJson ( filename : string ) : boolean {
72+ function readJsonFile ( filePath : string ) : unknown | null {
73+ try {
74+ return JSON . parse ( fs . readFileSync ( filePath , "utf8" ) ) ;
75+ } catch {
76+ return null ;
77+ }
78+ }
79+
80+ function normalizePackageTarget ( target : string ) : string {
81+ return target . replace ( / \\ / g, "/" ) . replace ( / ^ \. \/ / , "" ) ;
82+ }
83+
84+ function collectExportTargets ( value : unknown , targets : string [ ] ) : void {
85+ if ( typeof value === "string" ) {
86+ targets . push ( normalizePackageTarget ( value ) ) ;
87+ return ;
88+ }
89+
90+ if ( ! value || typeof value !== "object" ) return ;
91+
92+ if ( Array . isArray ( value ) ) {
93+ for ( const item of value ) collectExportTargets ( item , targets ) ;
94+ return ;
95+ }
96+
97+ for ( const nested of Object . values ( value ) ) {
98+ collectExportTargets ( nested , targets ) ;
99+ }
100+ }
101+
102+ export function findNearestPackageJson ( filename : string ) : string | null {
73103 let dir = path . dirname ( filename ) ;
74104 const root = path . parse ( dir ) . root || "/" ;
75- while ( dir !== root ) {
76- if ( fileExists ( path . join ( dir , "package.json" ) ) ) return true ;
105+ while ( true ) {
106+ const packageJsonPath = path . join ( dir , "package.json" ) ;
107+ if ( fileExists ( packageJsonPath ) ) return packageJsonPath ;
108+ if ( dir === root ) return null ;
77109 dir = path . dirname ( dir ) ;
78110 }
79- return false ;
111+ }
112+
113+ export function getPackageName ( filename : string ) : string | null {
114+ const packageJsonPath = findNearestPackageJson ( filename ) ;
115+ if ( ! packageJsonPath ) return null ;
116+ const parsed = readJsonFile ( packageJsonPath ) ;
117+ if ( ! parsed || typeof parsed !== "object" ) return null ;
118+ const name = ( parsed as { name ?: unknown } ) . name ;
119+ return typeof name === "string" && name . length > 0 ? name : null ;
120+ }
121+
122+ export function hasPackageJson ( filename : string ) : boolean {
123+ return findNearestPackageJson ( filename ) !== null ;
124+ }
125+
126+ export function isPackageEntrypoint ( filename : string ) : boolean {
127+ const packageJsonPath = findNearestPackageJson ( filename ) ;
128+ if ( ! packageJsonPath ) return false ;
129+
130+ const parsed = readJsonFile ( packageJsonPath ) ;
131+ if ( ! parsed || typeof parsed !== "object" ) return false ;
132+
133+ const packageDir = path . dirname ( packageJsonPath ) ;
134+ const relativeFilename = path
135+ . relative ( packageDir , filename )
136+ . replace ( / \\ / g, "/" ) ;
137+ if ( ! relativeFilename || relativeFilename . startsWith ( "../" ) ) return false ;
138+
139+ const manifest = parsed as {
140+ main ?: unknown ;
141+ module ?: unknown ;
142+ types ?: unknown ;
143+ typings ?: unknown ;
144+ exports ?: unknown ;
145+ } ;
146+ const entrypoints : string [ ] = [ ] ;
147+
148+ for ( const field of [
149+ manifest . main ,
150+ manifest . module ,
151+ manifest . types ,
152+ manifest . typings ,
153+ ] ) {
154+ if ( typeof field === "string" ) {
155+ entrypoints . push ( normalizePackageTarget ( field ) ) ;
156+ }
157+ }
158+
159+ collectExportTargets ( manifest . exports , entrypoints ) ;
160+
161+ return entrypoints . includes ( relativeFilename ) ;
80162}
0 commit comments