1
- const { spawn : nodeSpawn } = require ( 'node:child_process' ) ;
2
- const fs = require ( 'node:fs/promises' ) ;
1
+ import {
2
+ spawn as nodeSpawn ,
3
+ SpawnOptionsWithoutStdio ,
4
+ } from 'node:child_process' ;
5
+ import fs from 'node:fs/promises' ;
3
6
4
- const deepEqual = require ( 'deep-equal' ) ;
5
- const kleur = require ( 'kleur' ) ;
7
+ import deepEqual from 'deep-equal' ;
8
+ import kleur from 'kleur' ;
9
+ import { compare , parse } from 'semver' ;
10
+
11
+ type VersionCache = Record < string , string > ;
6
12
7
13
const VERSION_CACHE_PATH = './source/_data/versionCache.json' ;
8
14
9
15
/**
10
16
* Promise version of `spawn` to avoid blocking the main thread while waiting
11
17
* for the child processes.
12
18
*/
13
- const spawn = ( cmd , args , options ) => {
19
+ const spawn = (
20
+ cmd : string ,
21
+ args : string [ ] ,
22
+ options : SpawnOptionsWithoutStdio ,
23
+ ) => {
14
24
return new Promise ( ( resolve , reject ) => {
15
25
const child = nodeSpawn ( cmd , args , options ) ;
16
- const stderr = [ ] ;
17
- const stdout = [ ] ;
18
- child . stdout . on ( 'data' , ( data ) => {
26
+ const stderr : string [ ] = [ ] ;
27
+ const stdout : string [ ] = [ ] ;
28
+ child . stdout . on ( 'data' , ( data : Buffer ) => {
19
29
stdout . push ( data . toString ( ) ) ;
20
30
} ) ;
21
- child . on ( 'error' , ( e ) => {
31
+ child . on ( 'error' , ( e : Error ) => {
22
32
stderr . push ( e . toString ( ) ) ;
23
33
} ) ;
24
34
child . on ( 'close' , ( ) => {
@@ -35,14 +45,12 @@ const spawn = (cmd, args, options) => {
35
45
* Retrieves cached version object from cache file.
36
46
*/
37
47
const getCacheFile = async ( ) => {
38
- if ( process . env . NETLIFY || process . env . REBUILD_VERSION_CACHE ) {
39
- return { } ;
40
- }
41
48
let versionCache ;
42
49
try {
43
- versionCache = JSON . parse ( await fs . readFile ( VERSION_CACHE_PATH ) ) ;
50
+ const versionFile = await fs . readFile ( VERSION_CACHE_PATH ) ;
51
+ versionCache = JSON . parse ( versionFile . toString ( ) ) as VersionCache ;
44
52
} catch ( err ) {
45
- if ( err . code === 'ENOENT' ) {
53
+ if ( ( err as NodeJS . ErrnoException ) . code === 'ENOENT' ) {
46
54
versionCache = { } ; // Cache is missing and needs to be created
47
55
} else {
48
56
throw err ;
@@ -54,7 +62,7 @@ const getCacheFile = async () => {
54
62
/**
55
63
* Writes version object to cache file.
56
64
*/
57
- const writeCacheFile = async ( cache ) => {
65
+ const writeCacheFile = async ( cache : VersionCache ) => {
58
66
// eslint-disable-next-line no-console
59
67
console . info ( kleur . green ( `[11ty] Writing version cache file...` ) ) ;
60
68
await fs . writeFile ( VERSION_CACHE_PATH , JSON . stringify ( cache ) ) ;
@@ -63,39 +71,37 @@ const writeCacheFile = async (cache) => {
63
71
/**
64
72
* Retrieves the highest stable version of `repo`, based on its git tags.
65
73
*/
66
- const getLatestVersion = async ( repo ) => {
74
+ const getLatestVersion = async ( repo : string ) => {
67
75
// eslint-disable-next-line no-console
68
76
console . info ( kleur . cyan ( `[11ty] Fetching version information for ${ repo } ` ) ) ;
69
- const { parseSemVer, compareSemVer } = await import ( 'semver-parser' ) ;
70
77
let stdout ;
71
78
try {
72
- stdout = await spawn (
79
+ stdout = ( await spawn (
73
80
'git' ,
74
81
[ 'ls-remote' , '--tags' , '--refs' , `https://github.com/${ repo } ` ] ,
75
- { env : { ...process . env , GIT_TERMINAL_PROMPT : 0 } } ,
76
- ) ;
82
+ { env : { ...process . env , GIT_TERMINAL_PROMPT : '0' } } ,
83
+ ) ) as string ;
77
84
} catch ( err ) {
78
85
// eslint-disable-next-line no-console
79
86
console . error ( kleur . red ( `[11ty] Failed to fetch git tags for ${ repo } ` ) ) ;
80
87
throw err ;
81
88
}
82
- const isNotPreRelease = ( version ) => {
83
- const parsed = parseSemVer ( version ) ;
84
- return parsed . matches && ! parsed . pre ;
89
+ const isNotPreRelease = ( version : string ) => {
90
+ const parsed = parse ( version ) ;
91
+ return parsed && parsed . prerelease . length === 0 ;
85
92
} ;
86
93
const version = stdout
87
94
. split ( '\n' )
88
- . map ( ( line ) => line . split ( 'refs/tags/' ) . at ( - 1 ) )
95
+ . map ( ( line ) => line . split ( 'refs/tags/' ) . at ( - 1 ) ?? '' )
89
96
. filter ( isNotPreRelease )
90
- . sort ( compareSemVer )
97
+ . sort ( compare )
91
98
. at ( - 1 ) ;
92
99
93
- return version ;
100
+ return version ?? '' ;
94
101
} ;
95
102
96
103
/**
97
- * Returns the version and URL for the latest release of the given
98
- * implementation.
104
+ * Returns the version and URL for the latest release of all implementations.
99
105
*/
100
106
module . exports = async ( ) => {
101
107
const repos = [ 'sass/libsass' , 'sass/dart-sass' , 'sass/migrator' ] ;
@@ -114,7 +120,7 @@ module.exports = async () => {
114
120
] ) ,
115
121
) ;
116
122
117
- const nextCache = Object . fromEntries ( versions ) ;
123
+ const nextCache = Object . fromEntries ( versions ) as VersionCache ;
118
124
if ( ! deepEqual ( cache , nextCache ) ) {
119
125
await writeCacheFile ( nextCache ) ;
120
126
}
0 commit comments