1- import { readFileSync } from "node:fs" ;
2- import { dirname , resolve } from "node:path" ;
1+ import { readFileSync , readdirSync } from "node:fs" ;
2+ import { dirname , relative , resolve , sep } from "node:path" ;
33import { fileURLToPath } from "node:url" ;
44import { describe , expect , it } from "vitest" ;
55
@@ -33,13 +33,43 @@ const ALLOWED_CHANNEL_BUNDLED_METADATA_CONSUMERS = new Set([
3333 "src/channels/plugins/session-conversation.bundled-fallback.test.ts" ,
3434] ) ;
3535
36+ type FileFilter = {
37+ excludeTests ?: boolean ;
38+ testOnly ?: boolean ;
39+ } ;
40+
41+ function listTsFiles ( rootRelativePath : string , filter : FileFilter = { } ) : string [ ] {
42+ const root = resolve ( REPO_ROOT , rootRelativePath ) ;
43+ const files : string [ ] = [ ] ;
44+
45+ function walk ( directory : string ) {
46+ for ( const entry of readdirSync ( directory , { withFileTypes : true } ) ) {
47+ const fullPath = resolve ( directory , entry . name ) ;
48+ if ( entry . isDirectory ( ) ) {
49+ walk ( fullPath ) ;
50+ continue ;
51+ }
52+ if ( ! entry . isFile ( ) || ! entry . name . endsWith ( ".ts" ) ) {
53+ continue ;
54+ }
55+ const repoRelativePath = relative ( REPO_ROOT , fullPath ) . split ( sep ) . join ( "/" ) ;
56+ if ( filter . excludeTests && repoRelativePath . endsWith ( ".test.ts" ) ) {
57+ continue ;
58+ }
59+ if ( filter . testOnly && ! repoRelativePath . endsWith ( ".test.ts" ) ) {
60+ continue ;
61+ }
62+ files . push ( repoRelativePath ) ;
63+ }
64+ }
65+
66+ walk ( root ) ;
67+ return files . toSorted ( ) ;
68+ }
69+
3670describe ( "plugin contract boundary invariants" , ( ) => {
37- it ( "keeps bundled-capability-metadata confined to contract/test inventory" , async ( ) => {
38- const { globSync } = await import ( "glob" ) ;
39- const files = globSync ( "src/**/*.ts" , {
40- cwd : REPO_ROOT ,
41- nodir : true ,
42- } ) ;
71+ it ( "keeps bundled-capability-metadata confined to contract/test inventory" , ( ) => {
72+ const files = listTsFiles ( "src" ) ;
4373 const offenders = files . filter ( ( file ) => {
4474 if ( ALLOWED_BUNDLED_CAPABILITY_METADATA_CONSUMERS . has ( file ) ) {
4575 return false ;
@@ -50,26 +80,17 @@ describe("plugin contract boundary invariants", () => {
5080 expect ( offenders ) . toEqual ( [ ] ) ;
5181 } ) ;
5282
53- it ( "keeps the bundled contract inventory out of non-test runtime code" , async ( ) => {
54- const { globSync } = await import ( "glob" ) ;
55- const files = globSync ( "src/**/*.ts" , {
56- cwd : REPO_ROOT ,
57- nodir : true ,
58- ignore : [ "src/**/*.test.ts" ] ,
59- } ) ;
83+ it ( "keeps the bundled contract inventory out of non-test runtime code" , ( ) => {
84+ const files = listTsFiles ( "src" , { excludeTests : true } ) ;
6085 const offenders = files . filter ( ( file ) => {
6186 const source = readFileSync ( resolve ( REPO_ROOT , file ) , "utf8" ) ;
6287 return source . includes ( "contracts/inventory/bundled-capability-metadata" ) ;
6388 } ) ;
6489 expect ( offenders ) . toEqual ( [ ] ) ;
6590 } ) ;
6691
67- it ( "keeps core tests off bundled extension deep imports" , async ( ) => {
68- const { globSync } = await import ( "glob" ) ;
69- const files = globSync ( "src/**/*.test.ts" , {
70- cwd : REPO_ROOT ,
71- nodir : true ,
72- } ) ;
92+ it ( "keeps core tests off bundled extension deep imports" , ( ) => {
93+ const files = listTsFiles ( "src" , { testOnly : true } ) ;
7394 const offenders = files . filter ( ( file ) => {
7495 if ( ALLOWED_EXTENSION_PATH_STRING_TESTS . has ( file ) ) {
7596 return false ;
@@ -84,12 +105,8 @@ describe("plugin contract boundary invariants", () => {
84105 expect ( offenders ) . toEqual ( [ ] ) ;
85106 } ) ;
86107
87- it ( "keeps plugin contract tests off bundled path helpers unless the test is explicitly about paths" , async ( ) => {
88- const { globSync } = await import ( "glob" ) ;
89- const files = globSync ( "src/plugins/contracts/**/*.test.ts" , {
90- cwd : REPO_ROOT ,
91- nodir : true ,
92- } ) ;
108+ it ( "keeps plugin contract tests off bundled path helpers unless the test is explicitly about paths" , ( ) => {
109+ const files = listTsFiles ( "src/plugins/contracts" , { testOnly : true } ) ;
93110 const offenders = files . filter ( ( file ) => {
94111 if ( ALLOWED_CONTRACT_BUNDLED_PATH_HELPERS . has ( file ) ) {
95112 return false ;
@@ -100,13 +117,8 @@ describe("plugin contract boundary invariants", () => {
100117 expect ( offenders ) . toEqual ( [ ] ) ;
101118 } ) ;
102119
103- it ( "keeps channel production code off bundled-plugin-metadata helpers" , async ( ) => {
104- const { globSync } = await import ( "glob" ) ;
105- const files = globSync ( "src/channels/**/*.ts" , {
106- cwd : REPO_ROOT ,
107- nodir : true ,
108- ignore : [ "src/channels/**/*.test.ts" ] ,
109- } ) ;
120+ it ( "keeps channel production code off bundled-plugin-metadata helpers" , ( ) => {
121+ const files = listTsFiles ( "src/channels" , { excludeTests : true } ) ;
110122 const offenders = files . filter ( ( file ) => {
111123 if ( ALLOWED_CHANNEL_BUNDLED_METADATA_CONSUMERS . has ( file ) ) {
112124 return false ;
@@ -117,13 +129,11 @@ describe("plugin contract boundary invariants", () => {
117129 expect ( offenders ) . toEqual ( [ ] ) ;
118130 } ) ;
119131
120- it ( "keeps contract loaders off hand-built bundled extension paths" , async ( ) => {
121- const { globSync } = await import ( "glob" ) ;
122- const files = globSync ( "src/{plugins,channels}/**/*.ts" , {
123- cwd : REPO_ROOT ,
124- nodir : true ,
125- ignore : [ "src/**/*.test.ts" ] ,
126- } ) ;
132+ it ( "keeps contract loaders off hand-built bundled extension paths" , ( ) => {
133+ const files = [
134+ ...listTsFiles ( "src/plugins" , { excludeTests : true } ) ,
135+ ...listTsFiles ( "src/channels" , { excludeTests : true } ) ,
136+ ] . toSorted ( ) ;
127137 const offenders = files . filter ( ( file ) => {
128138 const source = readFileSync ( resolve ( REPO_ROOT , file ) , "utf8" ) ;
129139 return / e x t e n s i o n s \/ \$ \{ | \. \. \/ \. \. \/ \. \. \/ \. \. \/ e x t e n s i o n s \/ / u. test ( source ) ;
0 commit comments