1- import type {
2- ProjectConfig ,
3- RulePrompt ,
4- SeriName
5- } from './types'
1+ import type { ProjectConfig , RulePrompt , SeriName } from './types'
62import * as fs from 'node:fs'
73import * as path from 'node:path'
84import { getNativeBinding } from '@/core/native-binding'
95
106interface SeriesFilterFns {
11- readonly resolveEffectiveIncludeSeries : (
12- topLevel ?: readonly string [ ] ,
13- typeSpecific ?: readonly string [ ]
14- ) => string [ ]
15- readonly matchesSeries : (
16- seriName : string | readonly string [ ] | null | undefined ,
17- effectiveIncludeSeries : readonly string [ ]
18- ) => boolean
7+ readonly resolveEffectiveIncludeSeries : ( topLevel ?: readonly string [ ] , typeSpecific ?: readonly string [ ] ) => string [ ]
8+ readonly matchesSeries : ( seriName : string | readonly string [ ] | null | undefined , effectiveIncludeSeries : readonly string [ ] ) => boolean
199 readonly resolveSubSeries : (
2010 topLevel ?: Readonly < Record < string , readonly string [ ] > > ,
2111 typeSpecific ?: Readonly < Record < string , readonly string [ ] > >
2212 ) => Record < string , string [ ] >
2313}
2414
25- function requireSeriesFilterFns ( ) : SeriesFilterFns {
15+ let seriesFilterFnsCache : SeriesFilterFns | undefined
16+
17+ function getSeriesFilterFns ( ) : SeriesFilterFns {
18+ if ( seriesFilterFnsCache != null ) return seriesFilterFnsCache
19+
2620 const candidate = getNativeBinding < SeriesFilterFns > ( )
2721 if ( candidate == null ) {
2822 throw new TypeError ( 'Native series-filter binding is required. Build or install the Rust NAPI package before running tnmsc.' )
2923 }
30- if ( typeof candidate . matchesSeries !== 'function'
24+ if (
25+ typeof candidate . matchesSeries !== 'function'
3126 || typeof candidate . resolveEffectiveIncludeSeries !== 'function'
32- || typeof candidate . resolveSubSeries !== 'function' ) {
27+ || typeof candidate . resolveSubSeries !== 'function'
28+ ) {
3329 throw new TypeError ( 'Native series-filter binding is incomplete. Rebuild the Rust NAPI package before running tnmsc.' )
3430 }
31+ seriesFilterFnsCache = candidate
3532 return candidate
3633}
3734
38- const {
39- resolveEffectiveIncludeSeries,
40- matchesSeries,
41- resolveSubSeries
42- } : SeriesFilterFns = requireSeriesFilterFns ( )
35+ function resolveEffectiveIncludeSeries ( topLevel ?: readonly string [ ] , typeSpecific ?: readonly string [ ] ) : string [ ] {
36+ return getSeriesFilterFns ( ) . resolveEffectiveIncludeSeries ( topLevel , typeSpecific )
37+ }
38+
39+ function matchesSeries ( seriName : string | readonly string [ ] | null | undefined , effectiveIncludeSeries : readonly string [ ] ) : boolean {
40+ return getSeriesFilterFns ( ) . matchesSeries ( seriName , effectiveIncludeSeries )
41+ }
42+
43+ function resolveSubSeries (
44+ topLevel ?: Readonly < Record < string , readonly string [ ] > > ,
45+ typeSpecific ?: Readonly < Record < string , readonly string [ ] > >
46+ ) : Record < string , string [ ] > {
47+ return getSeriesFilterFns ( ) . resolveSubSeries ( topLevel , typeSpecific )
48+ }
4349
4450/**
4551 * Interface for items that can be filtered by series name
@@ -58,10 +64,7 @@ export function filterByProjectConfig<T extends SeriesFilterable>(
5864 projectConfig : ProjectConfig | undefined ,
5965 configPath : FilterConfigPath
6066) : readonly T [ ] {
61- const effectiveSeries = resolveEffectiveIncludeSeries (
62- projectConfig ?. includeSeries ,
63- projectConfig ?. [ configPath ] ?. includeSeries
64- )
67+ const effectiveSeries = resolveEffectiveIncludeSeries ( projectConfig ?. includeSeries , projectConfig ?. [ configPath ] ?. includeSeries )
6568 return items . filter ( item => matchesSeries ( item . seriName , effectiveSeries ) )
6669}
6770
@@ -77,10 +80,7 @@ function smartConcatGlob(prefix: string, glob: string): string {
7780 return `${ prefix } /${ glob } `
7881}
7982
80- function extractPrefixAndBaseGlob (
81- glob : string ,
82- prefixes : readonly string [ ]
83- ) : { prefix : string | null , baseGlob : string } {
83+ function extractPrefixAndBaseGlob ( glob : string , prefixes : readonly string [ ] ) : { prefix : string | null , baseGlob : string } {
8484 for ( const prefix of prefixes ) {
8585 const normalizedPrefix = prefix . replaceAll ( / \/ + $ / g, '' )
8686 const patterns = [
@@ -95,10 +95,7 @@ function extractPrefixAndBaseGlob(
9595 return { prefix : null , baseGlob : glob }
9696}
9797
98- export function applySubSeriesGlobPrefix (
99- rules : readonly RulePrompt [ ] ,
100- projectConfig : ProjectConfig | undefined
101- ) : readonly RulePrompt [ ] {
98+ export function applySubSeriesGlobPrefix ( rules : readonly RulePrompt [ ] , projectConfig : ProjectConfig | undefined ) : readonly RulePrompt [ ] {
10299 const subSeries = resolveSubSeries ( projectConfig ?. subSeries , projectConfig ?. rules ?. subSeries )
103100 if ( Object . keys ( subSeries ) . length === 0 ) return rules
104101
@@ -115,9 +112,7 @@ export function applySubSeriesGlobPrefix(
115112
116113 const matchedPrefixes : string [ ] = [ ]
117114 for ( const [ subdir , seriNames ] of Object . entries ( normalizedSubSeries ) ) {
118- const matched = Array . isArray ( rule . seriName )
119- ? rule . seriName . some ( name => seriNames . includes ( name ) )
120- : seriNames . includes ( rule . seriName )
115+ const matched = Array . isArray ( rule . seriName ) ? rule . seriName . some ( name => seriNames . includes ( name ) ) : seriNames . includes ( rule . seriName )
121116 if ( matched ) matchedPrefixes . push ( subdir )
122117 }
123118
@@ -168,9 +163,7 @@ export function resolveGitInfoDir(projectDir: string): string | null {
168163 const gitdir = path . resolve ( projectDir , match [ 1 ] )
169164 return path . join ( gitdir , 'info' )
170165 }
171- }
172- catch {
173- } // ignore read errors
166+ } catch { } // ignore read errors
174167 }
175168
176169 return null
@@ -193,8 +186,7 @@ export function findAllGitRepos(rootDir: string, maxDepth = 5): string[] {
193186 const raw = fs . readdirSync ( dir , { withFileTypes : true } )
194187 if ( ! Array . isArray ( raw ) ) return
195188 entries = raw
196- }
197- catch {
189+ } catch {
198190 return
199191 }
200192
@@ -229,8 +221,7 @@ export function findGitModuleInfoDirs(dotGitDir: string): string[] {
229221 const raw = fs . readdirSync ( dir , { withFileTypes : true } )
230222 if ( ! Array . isArray ( raw ) ) return
231223 entries = raw
232- }
233- catch {
224+ } catch {
234225 return
235226 }
236227
@@ -245,8 +236,7 @@ export function findGitModuleInfoDirs(dotGitDir: string): string[] {
245236 const raw = fs . readdirSync ( path . join ( dir , 'modules' ) , { withFileTypes : true } )
246237 if ( ! Array . isArray ( raw ) ) return
247238 subEntries = raw
248- }
249- catch {
239+ } catch {
250240 return
251241 }
252242 for ( const sub of subEntries ) {
@@ -259,8 +249,7 @@ export function findGitModuleInfoDirs(dotGitDir: string): string[] {
259249 const raw = fs . readdirSync ( modulesDir , { withFileTypes : true } )
260250 if ( ! Array . isArray ( raw ) ) return results
261251 topEntries = raw
262- }
263- catch {
252+ } catch {
264253 return results
265254 }
266255
0 commit comments