11#!/usr/bin/env node
22
3+ import os from 'node:os' ;
34import path from 'node:path' ;
45import { fileURLToPath } from 'node:url' ;
56import { Command } from 'commander' ;
@@ -16,10 +17,27 @@ const packageJson = JSON.parse(
1617) ;
1718
1819const 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` ,
2123 ) ;
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+ }
2341
2442 if ( typeof data === 'string' && data . startsWith ( 'version not found' ) ) {
2543 console . error ( `Tag ${ tag } does not exist for ${ packageName } .` ) ;
@@ -61,38 +79,46 @@ const init = async (name, { tag }) => {
6179 fse . copySync ( templatePath , resolvedProjectPath , {
6280 recursive : true ,
6381 } ) ;
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+ }
96122} ;
97123
98124new Command ( )
0 commit comments