11#!/usr/bin/env node
22
3- import os from 'node:os' ;
4- import path from 'node:path' ;
5- import { fileURLToPath } from 'node:url' ;
6- import { Command } from 'commander' ;
7- import fse from 'fs-extra' ;
8- import logSymbols from 'log-symbols' ;
9- import ora from 'ora' ;
10- import { tree } from './tree.js' ;
3+ import path from "node:path" ;
4+ import { fileURLToPath } from "node:url" ;
5+ import { Command } from "commander" ;
6+ import fse from "fs-extra" ;
7+ import logSymbols from "log-symbols" ;
8+ import ora from "ora" ;
9+ import { tree } from "./tree.js" ;
1110
1211const filename = fileURLToPath ( import . meta. url ) ;
1312const dirname = path . dirname ( filename ) ;
1413
1514const packageJson = JSON . parse (
16- fse . readFileSync ( path . resolve ( dirname , ' ../package.json' ) , ' utf8' ) ,
15+ fse . readFileSync ( path . resolve ( dirname , " ../package.json" ) , " utf8" ) ,
1716) ;
1817
1918const getLatestVersionOfTag = async ( packageName , tag ) => {
20- const cachePath = path . resolve (
21- os . tmpdir ( ) ,
22- `${ packageName . replaceAll ( '/' , '-' ) } -${ tag } .json` ,
23- ) ;
19+ const cacheFilename = `${ packageName . replaceAll ( "/" , "-" ) } -${ tag } .json` ;
20+
21+ const cacheDir = path . join ( path . dirname ( fileURLToPath ( import . meta. url ) ) , '..' , '.cache' ) ;
22+
23+ if ( ! fse . existsSync ( cacheDir ) ) {
24+ fse . mkdirSync ( cacheDir , { recursive : true , mode : 0o700 } ) ;
25+ }
26+
27+ const cachePath = path . join ( cacheDir , cacheFilename ) ;
28+
2429 let data ;
2530 try {
2631 const response = await fetch (
2732 `https://registry.npmjs.org/${ packageName } /${ tag } ` ,
2833 ) ;
2934 data = await response . json ( ) ;
30- await fse . writeFile ( cachePath , JSON . stringify ( data ) ) ;
35+
36+ fse . writeFileSync ( cachePath , JSON . stringify ( data ) , { mode : 0o600 } ) ;
3137 } catch ( exception ) {
3238 if ( fse . existsSync ( cachePath ) ) {
3339 console . warn (
3440 `${ logSymbols . warning } Failed to fetch the latest version from npm, using a cache` ,
3541 ) ;
36- data = await fse . readJson ( cachePath ) ;
42+ data = fse . readJSONSync ( cachePath ) ;
3743 } else {
3844 throw exception ;
3945 }
4046 }
4147
42- if ( typeof data === ' string' && data . startsWith ( ' version not found' ) ) {
48+ if ( typeof data === " string" && data . startsWith ( " version not found" ) ) {
4349 console . error ( `Tag ${ tag } does not exist for ${ packageName } .` ) ;
4450 process . exit ( 1 ) ;
4551 }
4652
4753 const { version } = data ;
4854
4955 if ( ! / ^ \d + \. \d + \. \d + .* $ / . test ( version ) ) {
50- console . error ( ' Invalid version received, something has gone very wrong.' ) ;
56+ console . error ( " Invalid version received, something has gone very wrong." ) ;
5157 }
52-
58+
5359 return version ;
5460} ;
5561
5662const init = async ( name , { tag } ) => {
5763 let projectPath = name ;
5864
5965 if ( ! projectPath ) {
60- projectPath = path . join ( process . cwd ( ) , ' react-email-starter' ) ;
66+ projectPath = path . join ( process . cwd ( ) , " react-email-starter" ) ;
6167 }
6268
63- if ( typeof projectPath === ' string' ) {
69+ if ( typeof projectPath === " string" ) {
6470 projectPath = projectPath . trim ( ) ;
6571 }
6672
67- const templatePath = path . resolve ( dirname , ' ../template' ) ;
73+ const templatePath = path . resolve ( dirname , " ../template" ) ;
6874 const resolvedProjectPath = path . resolve ( projectPath ) ;
6975
7076 if ( fse . existsSync ( resolvedProjectPath ) ) {
@@ -73,51 +79,51 @@ const init = async (name, { tag }) => {
7379 }
7480
7581 const spinner = ora ( {
76- text : ' Preparing files...\n' ,
82+ text : " Preparing files...\n" ,
7783 } ) . start ( ) ;
7884
7985 fse . copySync ( templatePath , resolvedProjectPath , {
8086 recursive : true ,
8187 } ) ;
8288 const templatePackageJsonPath = path . resolve (
8389 resolvedProjectPath ,
84- ' ./package.json' ,
90+ " ./package.json" ,
8591 ) ;
86- const templatePackageJson = fse . readFileSync ( templatePackageJsonPath , ' utf8' ) ;
92+ const templatePackageJson = fse . readFileSync ( templatePackageJsonPath , " utf8" ) ;
8793 fse . writeFileSync (
8894 templatePackageJsonPath ,
8995 templatePackageJson
9096 . replace (
91- ' INSERT_COMPONENTS_VERSION' ,
92- await getLatestVersionOfTag ( ' @react-email/components' , tag ) ,
97+ " INSERT_COMPONENTS_VERSION" ,
98+ await getLatestVersionOfTag ( " @react-email/components" , tag ) ,
9399 )
94100 . replace (
95- ' INSERT_REACT_EMAIL_VERSION' ,
96- await getLatestVersionOfTag ( ' react-email' , tag ) ,
101+ " INSERT_REACT_EMAIL_VERSION" ,
102+ await getLatestVersionOfTag ( " react-email" , tag ) ,
97103 ) ,
98- ' utf8' ,
104+ " utf8" ,
99105 ) ;
100106
101107 spinner . stopAndPersist ( {
102108 symbol : logSymbols . success ,
103- text : ' React Email Starter files ready' ,
109+ text : " React Email Starter files ready" ,
104110 } ) ;
105111
106112 // eslint-disable-next-line no-console
107113 console . info (
108114 await tree ( resolvedProjectPath , 4 , ( dirent ) => {
109115 return ! path
110116 . join ( dirent . parentPath , dirent . name )
111- . includes ( ' node_modules' ) ;
117+ . includes ( " node_modules" ) ;
112118 } ) ,
113119 ) ;
114120} ;
115121
116122new Command ( )
117123 . name ( packageJson . name )
118124 . version ( packageJson . version )
119- . description ( ' The easiest way to get started with React Email' )
120- . arguments ( ' [dir]' , ' Path to initialize the project' )
121- . option ( ' -t, --tag <tag>' , ' Tag of React Email versions to use' , ' latest' )
125+ . description ( " The easiest way to get started with React Email" )
126+ . arguments ( " [dir]" , " Path to initialize the project" )
127+ . option ( " -t, --tag <tag>" , " Tag of React Email versions to use" , " latest" )
122128 . action ( init )
123129 . parse ( process . argv ) ;
0 commit comments