@@ -56,22 +56,27 @@ var TERMS_META = [
56
56
/** @typedef {String } VersionString */
57
57
/** @typedef {Object.<VersionString, Array<BuildAsset>> } PackagesByRelease */
58
58
59
+ /** @typedef {ProjectMeta & ProjectInfoPartial } ProjectInfo */
59
60
/**
60
- * @typedef ProjectInfo
61
- * @prop {Array<BuildAsset> } releases
61
+ * @typedef ProjectMeta
62
62
* @prop {Array<BuildAsset> } packages
63
63
* @prop {Object.<TripletString, PackagesByRelease> } releasesByTriplet
64
64
* @prop {Array<import('./build-classifier/types.js').ArchString> } arches
65
65
* @prop {Array<import('./build-classifier/types.js').OsString> } oses
66
66
* @prop {Array<import('./build-classifier/types.js').LibcString> } libcs
67
- * @prop {Array<String> } channels
68
67
* @prop {Array<String> } formats
69
68
* @prop {Array<String> } triplets
70
69
* @prop {Array<String> } versions
71
70
* @prop {Array<String> } lexvers
72
71
* @prop {Object.<String, String> } lexversMap
73
72
*/
74
73
74
+ /**
75
+ * @typedef ProjectInfoPartial
76
+ * @prop {Array<BuildAsset> } releases
77
+ * @prop {Array<String> } channels
78
+ */
79
+
75
80
/**
76
81
* @typedef BuildAsset
77
82
* @prop {String } name
@@ -83,6 +88,8 @@ var TERMS_META = [
83
88
* @prop {String } libc
84
89
* @prop {String } ext
85
90
* @prop {String } download
91
+ * @prop {import('./build-classifier/types.js').TargetTriplet } [target]
92
+ * @prop {String } [lexver]
86
93
*/
87
94
88
95
/**
@@ -100,6 +107,18 @@ var TERMS_META = [
100
107
* @prop {Error } target.error
101
108
*/
102
109
110
+ /**
111
+ * @typedef {Error & WebiErrorPartial } WebiError
112
+ * @typedef WebiErrorPartial
113
+ * @prop {String } code
114
+ * @prop {Number } status
115
+ */
116
+
117
+ /** @typedef {String } PathString */
118
+
119
+ /**
120
+ * @param {PathString } path
121
+ */
103
122
async function getPartialHeader ( path ) {
104
123
let readme = `${ path } /README.md` ;
105
124
let head = await readFirstBytes ( readme ) . catch ( function ( err ) {
@@ -112,8 +131,9 @@ async function getPartialHeader(path) {
112
131
return head ;
113
132
}
114
133
115
- // let fsOpen = util.promisify(Fs.open);
116
- // let fsRead = util.promisify(Fs.read);
134
+ /**
135
+ * @param {PathString } path
136
+ */
117
137
async function readFirstBytes ( path ) {
118
138
let start = 0 ;
119
139
let n = 1024 ;
@@ -126,15 +146,29 @@ async function readFirstBytes(path) {
126
146
return str ;
127
147
}
128
148
149
+ /** @type {Object.<String, Promise<void>> } */
129
150
let promises = { } ;
151
+
152
+ /**
153
+ * @param {import('../_example/releases.js')? } Releases
154
+ * @param {PathString } installersDir
155
+ * @param {PathString } cacheDir
156
+ * @param {PathString } name
157
+ * @param {Date? } [date]
158
+ */
130
159
async function getLatestBuilds ( Releases , installersDir , cacheDir , name , date ) {
131
160
console . info ( `[INFO] getLatestBuilds: ${ name } ` ) ;
132
161
133
162
if ( ! Releases ) {
134
163
Releases = require ( `${ installersDir } /${ name } /releases.js` ) ;
135
164
}
165
+ if ( ! Releases ) {
166
+ throw new Error ( 'unreachable: narrowing for type checker' ) ;
167
+ }
168
+
136
169
// TODO update all releases files with module.exports.xxxx = 'foo';
137
170
if ( ! Releases . latest ) {
171
+ //@ts -expect-error
138
172
Releases . latest = Releases ;
139
173
}
140
174
@@ -150,6 +184,12 @@ async function getLatestBuilds(Releases, installersDir, cacheDir, name, date) {
150
184
return await promises [ id ] ;
151
185
}
152
186
187
+ /**
188
+ * @param {import('../_example/releases.js') } Releases
189
+ * @param {PathString } cacheDir
190
+ * @param {PathString } name
191
+ * @param {Date? } [date]
192
+ */
153
193
async function getLatestBuildsInner ( Releases , cacheDir , name , date ) {
154
194
let data = await Releases . latest ( ) ;
155
195
@@ -191,11 +231,14 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
191
231
bc . orphanTerms = Object . assign ( { } , bc . ALL_TERMS ) ;
192
232
bc . unknownTerms = { } ;
193
233
bc . usedTerms = { } ;
234
+ /** @type {Array<String> } */
194
235
bc . formats = [ ] ;
195
236
bc . _triplets = { } ;
196
237
bc . _targetsByBuildIdCache = { } ;
238
+ /** @type {Object.<String, ProjectInfo> } */
197
239
bc . _caches = { } ;
198
240
bc . _staleAge = 15 * 60 * 1000 ;
241
+ /** @type {Object.<String, Array<String>> } */
199
242
bc . _allFormats = { } ;
200
243
bc . _allTriplets = { } ;
201
244
@@ -243,8 +286,8 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
243
286
let filepath = Path . join ( installersDir , name ) ;
244
287
let entry ;
245
288
try {
246
- entry = await Fs . lstat ( filepath ) ;
247
- Object . assign ( entry , { name : name } ) ;
289
+ let stat = await Fs . lstat ( filepath ) ;
290
+ entry = Object . assign ( stat , { name : name } ) ;
248
291
} catch ( e ) {
249
292
return { type : 'errors' , detail : 'not found' } ;
250
293
}
@@ -255,7 +298,7 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
255
298
256
299
/**
257
300
* Get project type and detail - alias, selfhosted, valid (and the invalids)
258
- * @param {fs.Stats|fs. Dirent } entry
301
+ * @param {Omit<import('fs'). Dirent, "path"|"parentPath"> } entry
259
302
*/
260
303
bc . getProjectTypeByEntry = async function ( entry ) {
261
304
let path = Path . join ( installersDir , entry . name ) ;
@@ -300,7 +343,9 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
300
343
let releasesPath = Path . join ( path , 'releases.js' ) ;
301
344
try {
302
345
void require ( releasesPath ) ;
303
- } catch ( err ) {
346
+ } catch ( _err ) {
347
+ /** @type {WebiError } */ // @ts -expect-error
348
+ let err = _err ;
304
349
if ( err . code !== 'MODULE_NOT_FOUND' ) {
305
350
return { type : 'errors' , detail : err } ;
306
351
}
@@ -315,9 +360,16 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
315
360
return { type : 'valid' , detail : true } ;
316
361
} ;
317
362
318
- // Typically a package is organized by release (ex: go has 1.20, 1.21, etc),
319
- // but we will organize by the build (ex: go1.20-darwin-arm64.tar.gz, etc).
320
- bc . getPackages = async function ( { Releases, name, date } ) {
363
+ /**
364
+ * Typically a package is organized by release (ex: go has 1.20, 1.21, etc),
365
+ * but we will organize by the build (ex: go1.20-darwin-arm64.tar.gz, etc).
366
+ *
367
+ * @param {Object } opts
368
+ * @param {import('../_example/releases.js')? } [opts.Releases]
369
+ * @param {PathString } opts.name
370
+ * @param {Date } opts.date
371
+ */
372
+ bc . getPackages = async function ( { Releases = null , name, date } ) {
321
373
if ( ! date ) {
322
374
date = new Date ( ) ;
323
375
}
@@ -342,6 +394,7 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
342
394
343
395
let projInfo = bc . _caches [ name ] ;
344
396
397
+ /** @type {ProjectMeta } */
345
398
let meta = {
346
399
// version info
347
400
versions : projInfo ?. versions || [ ] ,
@@ -360,20 +413,23 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
360
413
} ;
361
414
362
415
if ( ! projInfo ) {
416
+ let NULLSTRING = 'null' ;
363
417
let json = await Fs . readFile ( dataFile , 'ascii' ) . catch (
364
418
async function ( err ) {
365
419
if ( err . code !== 'ENOENT' ) {
366
420
throw err ;
367
421
}
368
422
369
- return null ;
423
+ return NULLSTRING ;
370
424
} ,
371
425
) ;
372
426
373
427
try {
374
428
projInfo = JSON . parse ( json ) ;
375
- } catch ( e ) {
376
- console . error ( `error: ${ dataFile } :\n\t${ e . message } ` ) ;
429
+ } catch ( _err ) {
430
+ /** @type {WebiError } */ // @ts -expect-error
431
+ let err = _err ;
432
+ console . error ( `error: ${ dataFile } :\n\t${ err . message } ` ) ;
377
433
projInfo = null ;
378
434
}
379
435
}
@@ -419,8 +475,13 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
419
475
} ;
420
476
421
477
// Makes sure that packages are updated once an hour, on average
478
+ /** @type {Array<String> } */
422
479
bc . _staleNames = [ ] ;
480
+ /** @type {ReturnType<typeof setTimeout>? } */
423
481
bc . _freshenTimeout = null ;
482
+ /**
483
+ * @param {Number? } [minDelay]
484
+ */
424
485
bc . freshenRandomPackage = async function ( minDelay ) {
425
486
if ( ! minDelay ) {
426
487
minDelay = 15 * 1000 ;
@@ -437,7 +498,7 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
437
498
let name = bc . _staleNames . pop ( ) ;
438
499
void ( await bc . getPackages ( {
439
500
//Releases: Releases,
440
- name : name ,
501
+ name : name || '' ,
441
502
date : new Date ( ) ,
442
503
} ) ) ;
443
504
console . info ( `[INFO] freshenRandomPackage: ${ name } ` ) ;
@@ -448,7 +509,9 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
448
509
let seed = Math . random ( ) ;
449
510
delay += seed * spread ;
450
511
451
- clearTimeout ( bc . _freshenTimeout ) ;
512
+ if ( bc . _freshenTimeout ) {
513
+ clearTimeout ( bc . _freshenTimeout ) ;
514
+ }
452
515
bc . _freshenTimeout = setTimeout ( bc . freshenRandomPackage , delay ) ;
453
516
bc . _freshenTimeout . unref ( ) ;
454
517
} ;
@@ -471,6 +534,8 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
471
534
* .tar.xz
472
535
* .xz
473
536
* .zip
537
+ *
538
+ * @param {Array<String> } formats
474
539
*/
475
540
bc . getSortedFormats = function ( formats ) {
476
541
/* jshint maxcomplexity: 25 */
@@ -579,6 +644,10 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
579
644
return exts ;
580
645
} ;
581
646
647
+ /**
648
+ * @param {Array<BuildAsset> } packages
649
+ * @param {Array<String> } formats
650
+ */
582
651
bc . selectPackage = function ( packages , formats ) {
583
652
if ( packages . length === 1 ) {
584
653
return packages [ 0 ] ;
@@ -767,6 +836,11 @@ BuildsCacher.create = function ({ ALL_TERMS, installers, caches }) {
767
836
return bc ;
768
837
} ;
769
838
839
+ /**
840
+ * @param {ReturnType<typeof BuildsCacher.create> } bc
841
+ * @param {ProjectInfo } projInfo
842
+ * @param {BuildAsset } build
843
+ */
770
844
BuildsCacher . _classify = function ( bc , projInfo , build ) {
771
845
/* jshint maxcomplexity: 25 */
772
846
let maybeInstallable = Triplet . maybeInstallable ( projInfo , build ) ;
@@ -947,7 +1021,11 @@ BuildsCacher.transformAndUpdate = function (name, projInfo, meta, date, bc) {
947
1021
} ;
948
1022
949
1023
// TODO
950
- // - tag channels
1024
+ // - tag channels
1025
+ /**
1026
+ * @param {ProjectInfo } projInfo
1027
+ * @param {ProjectMeta } meta
1028
+ */
951
1029
BuildsCacher . updateAndSortVersions = function ( projInfo , meta ) {
952
1030
for ( let build of projInfo . packages ) {
953
1031
let hasVersion = meta . versions . includes ( build . version ) ;
@@ -967,17 +1045,31 @@ BuildsCacher.updateAndSortVersions = function (projInfo, meta) {
967
1045
meta . versions . push ( version ) ;
968
1046
}
969
1047
970
- projInfo . packages . sort ( function ( a , b ) {
971
- if ( a . lexver > b . lexver ) {
972
- return - 1 ;
973
- }
974
- if ( a . lexver < b . lexver ) {
975
- return 1 ;
976
- }
977
- return 0 ;
978
- } ) ;
1048
+ projInfo . packages . sort ( BuildsCacher . sortByLexver ) ;
1049
+ } ;
1050
+
1051
+ /**
1052
+ * @typedef HasLexver
1053
+ * @prop {String } lexver
1054
+ */
1055
+
1056
+ /**
1057
+ * @param {HasLexver } a
1058
+ * @param {HasLexver } b
1059
+ */
1060
+ BuildsCacher . sortByLexver = function ( a , b ) {
1061
+ if ( a . lexver > b . lexver ) {
1062
+ return - 1 ;
1063
+ }
1064
+ if ( a . lexver < b . lexver ) {
1065
+ return 1 ;
1066
+ }
1067
+ return 0 ;
979
1068
} ;
980
1069
1070
+ /**
1071
+ * @param {ProjectMeta } meta
1072
+ */
981
1073
BuildsCacher . updateReleasesByTriplet = function ( meta ) {
982
1074
for ( let build of meta . packages ) {
983
1075
let target = build . target ;
0 commit comments