@@ -2,7 +2,9 @@ import { log } from './log';
2
2
//eslint-disable-next-line node/no-missing-import
3
3
import { findClosestPkgJsonPath } from 'vitefu' ;
4
4
import { readFileSync } from 'fs' ;
5
+ import { dirname } from 'path' ;
5
6
import { performance } from 'perf_hooks' ;
7
+ import { normalizePath } from 'vite' ;
6
8
7
9
interface Stat {
8
10
file : string ;
@@ -85,6 +87,27 @@ function formatPackageStats(pkgStats: PackageStats[]) {
85
87
return table ;
86
88
}
87
89
90
+ /**
91
+ * utility to get the package name a file belongs to
92
+ *
93
+ * @param {string } file to find package for
94
+ * @returns {path:string,name:string } tuple of path,name where name is the parsed package name and path is the normalized path to it
95
+ */
96
+ async function getClosestNamedPackage ( file : string ) : Promise < { name : string ; path : string } > {
97
+ let name = '$unknown' ;
98
+ let path = await findClosestPkgJsonPath ( file , ( pkgPath ) => {
99
+ const pkg = JSON . parse ( readFileSync ( pkgPath , 'utf-8' ) ) ;
100
+ if ( pkg . name != null ) {
101
+ name = pkg . name ;
102
+ return true ;
103
+ }
104
+ return false ;
105
+ } ) ;
106
+ // return normalized path with appended '/' so .startsWith works for future file checks
107
+ path = normalizePath ( dirname ( path ?? file ) ) + '/' ;
108
+ return { name, path } ;
109
+ }
110
+
88
111
export class VitePluginSvelteStats {
89
112
// package directory -> package name
90
113
private _packages : { path : string ; name : string } [ ] = [ ] ;
@@ -108,6 +131,7 @@ export class VitePluginSvelteStats {
108
131
if ( collection . finished ) {
109
132
throw new Error ( 'called after finish() has been used' ) ;
110
133
}
134
+ file = normalizePath ( file ) ;
111
135
const start = performance . now ( ) ;
112
136
const stat : Stat = { file, start, end : start } ;
113
137
return ( ) => {
@@ -133,54 +157,41 @@ export class VitePluginSvelteStats {
133
157
}
134
158
135
159
private async _finish ( collection : StatCollection ) {
136
- collection . finished = true ;
137
- const now = performance . now ( ) ;
138
- collection . duration = now - collection . collectionStart ;
139
- const logResult = collection . options . logResult ( collection ) ;
140
- if ( logResult ) {
141
- await this . _aggregateStatsResult ( collection ) ;
142
- log . info ( `${ collection . name } done.` , formatPackageStats ( collection . packageStats ! ) ) ;
143
- }
144
- // cut some ties to free it for garbage collection
145
- const index = this . _collections . indexOf ( collection ) ;
146
- this . _collections . splice ( index , 1 ) ;
147
- collection . stats . length = 0 ;
148
- collection . stats = [ ] ;
149
- if ( collection . packageStats ) {
150
- collection . packageStats . length = 0 ;
151
- collection . packageStats = [ ] ;
160
+ try {
161
+ collection . finished = true ;
162
+ const now = performance . now ( ) ;
163
+ collection . duration = now - collection . collectionStart ;
164
+ const logResult = collection . options . logResult ( collection ) ;
165
+ if ( logResult ) {
166
+ await this . _aggregateStatsResult ( collection ) ;
167
+ log . info ( `${ collection . name } done.` , formatPackageStats ( collection . packageStats ! ) ) ;
168
+ }
169
+ // cut some ties to free it for garbage collection
170
+ const index = this . _collections . indexOf ( collection ) ;
171
+ this . _collections . splice ( index , 1 ) ;
172
+ collection . stats . length = 0 ;
173
+ collection . stats = [ ] ;
174
+ if ( collection . packageStats ) {
175
+ collection . packageStats . length = 0 ;
176
+ collection . packageStats = [ ] ;
177
+ }
178
+ collection . start = ( ) => ( ) => { } ;
179
+ collection . finish = ( ) => { } ;
180
+ } catch ( e ) {
181
+ // this should not happen, but stats taking also should not break the process
182
+ log . debug . once ( `failed to finish stats for ${ collection . name } ` , e ) ;
152
183
}
153
- collection . start = ( ) => ( ) => { } ;
154
- collection . finish = ( ) => { } ;
155
184
}
156
185
157
186
private async _aggregateStatsResult ( collection : StatCollection ) {
158
187
const stats = collection . stats ;
159
188
for ( const stat of stats ) {
160
189
let pkg = this . _packages . find ( ( p ) => stat . file . startsWith ( p . path ) ) ;
161
190
if ( ! pkg ) {
162
- // check for package.json first
163
- let pkgPath = await findClosestPkgJsonPath ( stat . file ) ;
164
- if ( pkgPath ) {
165
- let path = pkgPath ?. replace ( / p a c k a g e .j s o n $ / , '' ) ;
166
- let name = JSON . parse ( readFileSync ( pkgPath , 'utf-8' ) ) . name ;
167
- if ( ! name ) {
168
- // some packages have nameless nested package.json
169
- pkgPath = await findClosestPkgJsonPath ( path ) ;
170
- if ( pkgPath ) {
171
- path = pkgPath ?. replace ( / p a c k a g e .j s o n $ / , '' ) ;
172
- name = JSON . parse ( readFileSync ( pkgPath , 'utf-8' ) ) . name ;
173
- }
174
- }
175
- if ( path && name ) {
176
- pkg = { path, name } ;
177
- this . _packages . push ( pkg ) ;
178
- }
179
- }
191
+ pkg = await getClosestNamedPackage ( stat . file ) ;
192
+ this . _packages . push ( pkg ) ;
180
193
}
181
- // TODO is it possible that we want to track files where there is no named packge.json as parent?
182
- // what do we want to do for that, try to find common root paths for different stats?
183
- stat . pkg = pkg ?. name ?? '$unknown' ;
194
+ stat . pkg = pkg . name ;
184
195
}
185
196
186
197
// group stats
0 commit comments