Skip to content

Commit 446a7aa

Browse files
committed
store the cache in a .cache directory in the package's location, and use safer permissions for the files
1 parent c8a0dc0 commit 446a7aa

File tree

2 files changed

+41
-34
lines changed

2 files changed

+41
-34
lines changed

packages/create-email/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.test
2+
.cache

packages/create-email/src/index.js

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,76 @@
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

1211
const filename = fileURLToPath(import.meta.url);
1312
const dirname = path.dirname(filename);
1413

1514
const packageJson = JSON.parse(
16-
fse.readFileSync(path.resolve(dirname, '../package.json'), 'utf8'),
15+
fse.readFileSync(path.resolve(dirname, "../package.json"), "utf8"),
1716
);
1817

1918
const 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

5662
const 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

116122
new 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

Comments
 (0)