11import * as util from "util" ;
22import fs from "fs" ;
3+ import { glob } from "fs/promises" ;
34import path from "path" ;
45import * as kl from "kolorist" ;
56import { pipeline } from "stream" ;
@@ -11,30 +12,85 @@ const streamPipeline = util.promisify(pipeline);
1112/* eslint-disable no-console */
1213
1314/**
14- * @typedef {{time: Record<string, string>, versions: Record<string, {dist: {tarball: string}}>} } NPMResponse
15+ * @typedef {{versions: Record<string, {dist: {tarball: string}}>, "dist-tags": Record<string, string >} } NPMResponse
1516 */
1617
18+ const root = path . join ( __dirname , ".." ) ;
19+ const versionReg = / \b (?: 1 0 | 1 1 ) \. \d + \. \d + (?: - [ 0 - 9 A - Z a - z . - ] + ) ? \b / g;
20+
21+ function sortVersions ( a , b ) {
22+ const [ releaseA , prereleaseA ] = a . split ( "-" ) ;
23+ const [ releaseB , prereleaseB ] = b . split ( "-" ) ;
24+ const semverA = releaseA . split ( "." ) . map ( Number ) ;
25+ const semverB = releaseB . split ( "." ) . map ( Number ) ;
26+
27+ for ( const i of [ 0 , 1 , 2 ] ) {
28+ const diff = semverA [ i ] - semverB [ i ] ;
29+ if ( diff !== 0 ) return diff ;
30+ }
31+
32+ if ( ! prereleaseA && prereleaseB ) return 1 ;
33+ if ( prereleaseA && ! prereleaseB ) return - 1 ;
34+ if ( ! prereleaseA && ! prereleaseB ) return 0 ;
35+
36+ const partsA = prereleaseA . split ( "." ) ;
37+ const partsB = prereleaseB . split ( "." ) ;
38+ for ( let i = 0 ; i < Math . max ( partsA . length , partsB . length ) ; i ++ ) {
39+ if ( partsA [ i ] === undefined ) return - 1 ;
40+ if ( partsB [ i ] === undefined ) return 1 ;
41+
42+ const numA = / ^ \d + $ / . test ( partsA [ i ] ) ;
43+ const numB = / ^ \d + $ / . test ( partsB [ i ] ) ;
44+ if ( numA && numB && + partsA [ i ] !== + partsB [ i ] ) {
45+ return + partsA [ i ] - + partsB [ i ] ;
46+ }
47+ if ( numA !== numB ) return numA ? - 1 : 1 ;
48+ if ( partsA [ i ] !== partsB [ i ] ) return partsA [ i ] < partsB [ i ] ? - 1 : 1 ;
49+ }
50+
51+ return 0 ;
52+ }
53+
1754( async ( ) => {
1855 const res = await fetch ( "https://registry.npmjs.org/preact" ) ;
1956
2057 /** @type {NPMResponse } */
2158 const json = await res . json ( ) ;
2259
23- const versions = Object . keys ( json . time ) . reduce ( ( acc , version ) => {
24- if ( / m o d i f i e d | c r e a t e d / . test ( version ) ) {
25- return acc ;
26- }
60+ const publishedVersions = Object . keys ( json . versions ) ;
61+ const versionsToFetch = new Set ( [ json [ "dist-tags" ] . latest ] ) ;
2762
28- const semver = version . split ( "." ) ;
29- if ( + semver [ 0 ] < 10 || ( + semver [ 0 ] === 10 && + semver [ 1 ] < 1 ) ) {
30- return acc ;
31- }
63+ for await ( const file of glob ( "test-e2e/tests/**/*.test.ts" , { cwd : root } ) ) {
64+ const text = fs
65+ . readFileSync ( path . join ( root , file ) , "utf8" )
66+ . replace ( / \/ \* [ \s \S ] * ?\* \/ / g, "" )
67+ . replace ( / \/ \/ .* / g, "" ) ;
68+ text . match ( versionReg ) ?. forEach ( version => versionsToFetch . add ( version ) ) ;
69+ }
3270
33- acc . push ( version ) ;
34- return acc ;
35- } , [ ] ) ;
71+ const pkg = fs . readFileSync ( path . join ( root , "package.json" ) , "utf8" ) ;
72+ pkg . replace ( / P R E A C T _ V E R S I O N = ( \d + ) / g, ( _ , major ) => {
73+ const matching = publishedVersions . filter ( v => v . startsWith ( `${ major } .` ) ) ;
74+ const stable = matching . filter ( v => ! v . includes ( "-" ) ) ;
75+ versionsToFetch . add (
76+ ( stable . length ? stable : matching ) . sort ( sortVersions ) . at ( - 1 ) ,
77+ ) ;
78+ return "" ;
79+ } ) ;
80+
81+ const extras = process . argv . slice ( 2 ) ;
82+ if ( process . env . PREACT_VERSION ?. match ( versionReg ) ) {
83+ extras . push ( process . env . PREACT_VERSION ) ;
84+ }
85+
86+ for ( const arg of extras ) {
87+ const version = arg . replace ( / ^ p r e a c t @ / , "" ) . replace ( / ^ v / , "" ) ;
88+ if ( ! json . versions [ version ] )
89+ throw new Error ( `Unknown preact version "${ arg } "` ) ;
90+ versionsToFetch . add ( version ) ;
91+ }
3692
37- for ( const version of versions ) {
93+ for ( const version of [ ... versionsToFetch ] . sort ( sortVersions ) ) {
3894 const tarball = json . versions [ version ] . dist . tarball ;
3995 const tgz = path . basename ( tarball ) ;
4096 const dest = path . join (
0 commit comments