@@ -83,6 +83,10 @@ type PackageManifest = {
8383 version ?: unknown ;
8484} ;
8585
86+ type PackageLock = {
87+ packages ?: Record < string , PackageManifest > ;
88+ } ;
89+
8690function toYamlLine ( rawLine : string ) : YamlLine {
8791 return {
8892 indentation : rawLine . length - rawLine . trimStart ( ) . length ,
@@ -148,23 +152,46 @@ function hasDependabotIgnoreEntry(source: string, dependencyName: string): boole
148152
149153function assertPackageMetadata ( ) : void {
150154 const packageManifest = JSON . parse ( readText ( new URL ( '../../package.json' , import . meta. url ) ) ) as PackageManifest ;
155+ const packageLock = JSON . parse ( readText ( new URL ( '../../package-lock.json' , import . meta. url ) ) ) as PackageLock ;
151156 assert . equal ( packageManifest . version , '1.16.0' ) ;
152- assert . equal ( packageManifest . engines ?. node , '>=20' ) ;
157+ assert . equal ( packageManifest . engines ?. node , '>=22' ) ;
158+ assert . equal ( packageManifest . dependencies ?. unpdf , '1.8.1' ) ;
159+ assert . equal ( packageLock . packages ?. [ '' ] . engines ?. node , '>=22' ) ;
160+ assert . equal ( packageLock . packages ?. [ '' ] . dependencies ?. unpdf , '1.8.1' ) ;
153161 assert . equal ( packageManifest . dependencies ?. [ 'express-rate-limit' ] , '^8.5.2' ) ;
154162}
155163
156164function assertReadmeNodePolicy ( readme : string ) : void {
157- assert . ok ( readme . includes ( 'Node.js 20 remains supported but is deprecated and end-of-life.' ) ) ;
158- assert . ok ( readme . includes ( 'Node.js 22 or later is recommended.' ) ) ;
159- assert . ok ( readme . includes ( 'Node.js 20 will be removed only in a future major release.' ) ) ;
165+ assert . ok ( readme . includes ( 'Node.js 22 or later is required.' ) ) ;
166+ assert . ok ( ! readme . includes ( 'Node.js 20' ) , 'README must not claim Node.js 20 support' ) ;
167+ for ( const formerPromise of [
168+ 'Node.js 20 remains supported' ,
169+ 'Node.js 20 will be removed' ,
170+ 'Node.js 22 or later is recommended' ,
171+ ] ) {
172+ assert . ok ( ! readme . includes ( formerPromise ) , `README must not retain: ${ formerPromise } ` ) ;
173+ }
174+ }
175+
176+ function assertClientGuideNodePolicy ( guide : string ) : void {
177+ assert . ok ( guide . includes ( 'Requires Node.js 22 or later.' ) ) ;
178+ assert . ok ( ! guide . includes ( 'Node.js 20' ) , 'client guide must not claim Node.js 20 support' ) ;
179+ for ( const formerPromise of [
180+ 'Requires Node.js 20' ,
181+ 'Node.js 20 remains supported' ,
182+ 'Node.js 20 will be removed' ,
183+ 'Node.js 22 or later is recommended' ,
184+ ] ) {
185+ assert . ok ( ! guide . includes ( formerPromise ) , `client guide must not retain: ${ formerPromise } ` ) ;
186+ }
160187}
161188
162189function assertCiMatrix ( ci : string ) : void {
163190 const matrix = ci . match ( / ^ \s * n o d e - v e r s i o n : \s * \[ ( [ ^ \] ] + ) \] \s * $ / mu) ;
164191 assert . ok ( matrix , 'CI must declare an inline Node version matrix' ) ;
165192 assert . deepEqual (
166193 [ ...matrix [ 1 ] . matchAll ( / [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / gu) ] . map ( ( match ) => match [ 1 ] ) ,
167- [ '20' , ' 22', '24' , '26.7.0' ] ,
194+ [ '22' , '24' , '26.7.0' ] ,
168195 ) ;
169196}
170197
@@ -174,9 +201,16 @@ function assertCiCommonJob(ci: string): void {
174201 assert . match ( ci , / u s e s : \s * a c t i o n s \/ c h e c k o u t @ / u) ;
175202 assert . match ( ci , / u s e s : \s * a c t i o n s \/ s e t u p - n o d e @ / u) ;
176203 assert . match ( ci , / c a c h e : \s * [ ' " ] n p m [ ' " ] / u) ;
177- for ( const command of [ / r u n : \s * n p m c i / u, / r u n : \s * n p m r u n l i n t / u, / r u n : \s * n p m r u n b u i l d / u, / r u n : \s * n p m r u n t e s t : c o v e r a g e / u] ) {
204+ for ( const command of [
205+ / r u n : \s * n p m c i / u,
206+ / r u n : \s * n p m r u n l i n t / u,
207+ / r u n : \s * n p m r u n b u i l d / u,
208+ / r u n : \s * n p m r u n t e s t : c o v e r a g e / u,
209+ / r u n : \s * n p m r u n t e s t : e 2 e / u,
210+ ] ) {
178211 assert . match ( ci , command ) ;
179212 }
213+ assert . match ( ci , / r u n : \s * n p m r u n t e s t : c o v e r a g e \s * \n \s * - n a m e : E 2 E t e s t s \s * \n \s * r u n : \s * n p m r u n t e s t : e 2 e / u) ;
180214 assert . doesNotMatch ( ci , / ^ \s * i n c l u d e \s * : / mu) ;
181215 assert . doesNotMatch ( ci , / ^ \s * i f \s * : / mu) ;
182216 assert . doesNotMatch ( ci , / c o n t i n u e - o n - e r r o r \s * : / u) ;
@@ -392,6 +426,7 @@ export async function runTests(): Promise<TestResult> {
392426 const dependabot = readText ( new URL ( '../../.github/dependabot.yml' , import . meta. url ) ) ;
393427 assertPackageMetadata ( ) ;
394428 assertReadmeNodePolicy ( readme ) ;
429+ assertClientGuideNodePolicy ( readText ( guideUrl ) ) ;
395430 assertCiMatrix ( ci ) ;
396431 assertCiCommonJob ( ci ) ;
397432 assertCodeqlActionPins ( codeql ) ;
0 commit comments