1
1
#!/usr/bin/env node
2
2
3
+ import os from 'node:os' ;
3
4
import path from 'node:path' ;
4
5
import { fileURLToPath } from 'node:url' ;
5
6
import { Command } from 'commander' ;
@@ -16,10 +17,27 @@ const packageJson = JSON.parse(
16
17
) ;
17
18
18
19
const getLatestVersionOfTag = async ( packageName , tag ) => {
19
- const response = await fetch (
20
- `https://registry.npmjs.org/${ packageName } /${ tag } ` ,
20
+ const cachePath = path . resolve (
21
+ os . tmpdir ( ) ,
22
+ `${ packageName . replaceAll ( '/' , '-' ) } -${ tag } .json` ,
21
23
) ;
22
- const data = await response . json ( ) ;
24
+ let data ;
25
+ try {
26
+ const response = await fetch (
27
+ `https://registry.npmjs.org/${ packageName } /${ tag } ` ,
28
+ ) ;
29
+ data = await response . json ( ) ;
30
+ await fse . writeFile ( cachePath , JSON . stringify ( data ) ) ;
31
+ } catch ( exception ) {
32
+ if ( fse . existsSync ( cachePath ) ) {
33
+ console . warn (
34
+ `${ logSymbols . warning } Failed to fetch the latest version from npm, using a cache` ,
35
+ ) ;
36
+ data = await fse . readJson ( cachePath ) ;
37
+ } else {
38
+ throw exception ;
39
+ }
40
+ }
23
41
24
42
if ( typeof data === 'string' && data . startsWith ( 'version not found' ) ) {
25
43
console . error ( `Tag ${ tag } does not exist for ${ packageName } .` ) ;
@@ -61,38 +79,46 @@ const init = async (name, { tag }) => {
61
79
fse . copySync ( templatePath , resolvedProjectPath , {
62
80
recursive : true ,
63
81
} ) ;
64
- const templatePackageJsonPath = path . resolve (
65
- resolvedProjectPath ,
66
- './package.json' ,
67
- ) ;
68
- const templatePackageJson = fse . readFileSync ( templatePackageJsonPath , 'utf8' ) ;
69
- fse . writeFileSync (
70
- templatePackageJsonPath ,
71
- templatePackageJson
72
- . replace (
73
- 'INSERT_COMPONENTS_VERSION' ,
74
- await getLatestVersionOfTag ( '@react-email/components' , tag ) ,
75
- )
76
- . replace (
77
- 'INSERT_REACT_EMAIL_VERSION' ,
78
- await getLatestVersionOfTag ( 'react-email' , tag ) ,
79
- ) ,
80
- 'utf8' ,
81
- ) ;
82
-
83
- spinner . stopAndPersist ( {
84
- symbol : logSymbols . success ,
85
- text : 'React Email Starter files ready' ,
86
- } ) ;
87
-
88
- // eslint-disable-next-line no-console
89
- console . info (
90
- await tree ( resolvedProjectPath , 4 , ( dirent ) => {
91
- return ! path
92
- . join ( dirent . parentPath , dirent . name )
93
- . includes ( 'node_modules' ) ;
94
- } ) ,
95
- ) ;
82
+ try {
83
+ const templatePackageJsonPath = path . resolve (
84
+ resolvedProjectPath ,
85
+ './package.json' ,
86
+ ) ;
87
+ const templatePackageJson = fse . readFileSync (
88
+ templatePackageJsonPath ,
89
+ 'utf8' ,
90
+ ) ;
91
+ fse . writeFileSync (
92
+ templatePackageJsonPath ,
93
+ templatePackageJson
94
+ . replace (
95
+ 'INSERT_COMPONENTS_VERSION' ,
96
+ await getLatestVersionOfTag ( '@react-email/components' , tag ) ,
97
+ )
98
+ . replace (
99
+ 'INSERT_REACT_EMAIL_VERSION' ,
100
+ await getLatestVersionOfTag ( 'react-email' , tag ) ,
101
+ ) ,
102
+ 'utf8' ,
103
+ ) ;
104
+
105
+ spinner . stopAndPersist ( {
106
+ symbol : logSymbols . success ,
107
+ text : 'React Email Starter files ready' ,
108
+ } ) ;
109
+
110
+ // eslint-disable-next-line no-console
111
+ console . info (
112
+ await tree ( resolvedProjectPath , 4 , ( dirent ) => {
113
+ return ! path
114
+ . join ( dirent . parentPath , dirent . name )
115
+ . includes ( 'node_modules' ) ;
116
+ } ) ,
117
+ ) ;
118
+ } catch ( exception ) {
119
+ fse . removeSync ( resolvedProjectPath ) ;
120
+ throw exception ;
121
+ }
96
122
} ;
97
123
98
124
new Command ( )
0 commit comments