Skip to content

Commit f940313

Browse files
author
alexlee-dev
committed
✏️ Refactor 'copyTemplateFiles()'
1 parent f7a1941 commit f940313

4 files changed

Lines changed: 113 additions & 126 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616

1717
### Changed
1818

19+
- Refactored `copyTemplateFiles()`
20+
1921
### Removed
2022

2123
### Fixed

src/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
installDevDependencies,
2020
createTSConfig,
2121
displaySuccessMessage,
22+
replaceTemplateValues,
2223
} from "./init";
2324
import { handleIncorrectApplicationName } from "./program";
2425
import { cleanupError } from "./util";
@@ -124,8 +125,11 @@ const main = async (): Promise<void> => {
124125
// * Installs dev dependencies
125126
await installDevDependencies(applicationName, language);
126127

127-
// * Copies template files and inserts `applicationName` into the files
128-
await copyTemplateFiles(applicationName, language, authorName);
128+
// * Copies template files
129+
await copyTemplateFiles(applicationName, language);
130+
131+
// * Replaces template files placeholder values with real values for the application.
132+
await replaceTemplateValues(applicationName, language, authorName);
129133

130134
// * Creates a tsconfig.json file
131135
if (language === "ts") await createTSConfig(applicationName);

src/init.ts

Lines changed: 78 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import os from "os";
55
import path from "path";
66

77
import { dependencies, devDependencies, devDependenciesTS } from "./constants";
8-
import { executeCommand } from "./util";
8+
import { executeCommand, valueReplacer } from "./util";
99

1010
/**
1111
* Creates a project directory and a package.json inside that new directory.
@@ -131,16 +131,14 @@ export const installDevDependencies = async (
131131
}
132132
};
133133

134-
// TODO - Refactor this function :)
135134
/**
136-
* Copies template files and inserts values into the files.
135+
* Copies template files.
137136
* @param applicationName Name of application.
138137
* @param language Language of application.
139138
*/
140139
export const copyTemplateFiles = async (
141140
applicationName: string,
142-
language: "js" | "ts",
143-
authorName: string
141+
language: "js" | "ts"
144142
): Promise<void> => {
145143
// * Application Directory
146144
const root = path.resolve(applicationName);
@@ -149,139 +147,95 @@ export const copyTemplateFiles = async (
149147

150148
try {
151149
spinner.start();
152-
// * Copy template files based on language
153-
await fs.copy(
154-
path.join(__dirname, `template/${language}/src`),
155-
path.join(root, "/src")
156-
);
157-
await fs.copy(
158-
path.join(__dirname, "template/index.js"),
159-
path.join(root, "/index.js")
160-
);
161-
await fs.copy(
162-
path.join(__dirname, "template/README.md"),
163-
path.join(root, "/README.md")
164-
);
165-
await fs.copy(
166-
path.join(__dirname, "template/gitignore"),
167-
path.join(root, "/.gitignore")
150+
const requiredFilesToCopy = [
151+
{
152+
src: path.join(__dirname, `template/${language}/src`),
153+
dest: path.join(root, "/src"),
154+
},
155+
{
156+
src: path.join(__dirname, "template/index.js"),
157+
dest: path.join(root, "/index.js"),
158+
},
159+
{
160+
src: path.join(__dirname, "template/README.md"),
161+
dest: path.join(root, "/README.md"),
162+
},
163+
{
164+
src: path.join(__dirname, "template/gitignore"),
165+
dest: path.join(root, "/.gitignore"),
166+
},
167+
];
168+
169+
// * Copy Template Files
170+
await Promise.all(
171+
requiredFilesToCopy.map(
172+
async (fileInfo: { src: string; dest: string }) => {
173+
await fs.copy(fileInfo.src, fileInfo.dest);
174+
return;
175+
}
176+
)
168177
);
178+
179+
// * Copy .babelrc for JS projects
169180
if (language === "js") {
170181
await fs.copy(
171182
path.join(__dirname, "template/babelrc"),
172183
path.join(root, "/.babelrc")
173184
);
174185
}
175186

176-
// * Apply the applicationName to template files
177-
const readmeFile = await fs.readFile(path.join(root, "README.md"), "utf-8");
178-
const newReadmeContent = readmeFile.replace(
179-
/___APP NAME___/gm,
180-
applicationName
181-
);
182-
await fs.writeFile(path.join(root, "README.md"), newReadmeContent, "utf8");
187+
spinner.succeed("Template files copied successfully");
188+
} catch (error) {
189+
spinner.fail();
190+
throw new Error(error);
191+
}
192+
};
183193

184-
if (language === "js") {
185-
// * src/index.js
186-
const indexFile = await fs.readFile(
187-
path.join(root, "/src/index.js"),
188-
"utf-8"
189-
);
190-
const newIndexFileContent = indexFile.replace(
191-
/___APP NAME___/gm,
192-
applicationName
193-
);
194-
await fs.writeFile(
195-
path.join(root, "/src/index.js"),
196-
newIndexFileContent,
197-
"utf8"
198-
);
194+
/**
195+
* Replaces template files placeholder values with real values for the application.
196+
* @param applicationName Name of application.
197+
* @param language Language of application.
198+
* @param authorName Name of author.
199+
*/
200+
export const replaceTemplateValues = async (
201+
applicationName: string,
202+
language: "js" | "ts",
203+
authorName: string
204+
): Promise<void> => {
205+
// * Application Directory
206+
const root = path.resolve(applicationName);
199207

200-
// * src/menu.js
201-
const menuFile = await fs.readFile(
202-
path.join(root, "/src/menu.js"),
203-
"utf-8"
204-
);
205-
let newMenuFileContent = menuFile.replace(
206-
/___APP NAME___/gm,
207-
applicationName
208-
);
209-
newMenuFileContent = newMenuFileContent.replace(
210-
/___AUTHOR NAME___/gm,
211-
authorName
212-
);
213-
await fs.writeFile(
214-
path.join(root, "/src/menu.js"),
215-
newMenuFileContent,
216-
"utf8"
217-
);
208+
let spinner = ora("Replacing values in template files");
209+
try {
210+
spinner.start();
218211

219-
// * src/setup.js
220-
const setupFile = await fs.readFile(
221-
path.join(root, "/src/setup.js"),
222-
"utf-8"
223-
);
224-
const newSetupFileContent = setupFile.replace(
225-
/___APP NAME___/gm,
226-
applicationName
227-
);
228-
await fs.writeFile(
229-
path.join(root, "/src/setup.js"),
230-
newSetupFileContent,
231-
"utf8"
232-
);
233-
} else if (language === "ts") {
234-
// * src/index.ts
235-
const indexFile = await fs.readFile(
236-
path.join(root, "/src/index.ts"),
237-
"utf-8"
238-
);
239-
const newIndexFileContent = indexFile.replace(
240-
/___APP NAME___/gm,
241-
applicationName
242-
);
243-
await fs.writeFile(
244-
path.join(root, "/src/index.ts"),
245-
newIndexFileContent,
246-
"utf8"
247-
);
212+
const jsFilesToRewrite = [
213+
path.join(root, "README.md"),
214+
path.join(root, "/src/index.js"),
215+
path.join(root, "/src/menu.js"),
216+
path.join(root, "/src/setup.js"),
217+
];
218+
const tsFilesToRewrite = [
219+
path.join(root, "README.md"),
220+
path.join(root, "/src/index.ts"),
221+
path.join(root, "/src/menu.ts"),
222+
path.join(root, "/src/setup.ts"),
223+
];
248224

249-
// * src/menu.ts
250-
const menuFile = await fs.readFile(
251-
path.join(root, "/src/menu.ts"),
252-
"utf-8"
253-
);
254-
let newMenuFileContent = menuFile.replace(
255-
/___APP NAME___/gm,
256-
applicationName
257-
);
258-
newMenuFileContent = newMenuFileContent.replace(
259-
/___AUTHOR NAME___/gm,
260-
authorName
261-
);
262-
await fs.writeFile(
263-
path.join(root, "/src/menu.ts"),
264-
newMenuFileContent,
265-
"utf8"
266-
);
225+
let replaceFiles = jsFilesToRewrite;
267226

268-
// * src/setup.ts
269-
const setupFile = await fs.readFile(
270-
path.join(root, "/src/setup.ts"),
271-
"utf-8"
272-
);
273-
const newSetupFileContent = setupFile.replace(
274-
/___APP NAME___/gm,
275-
applicationName
276-
);
277-
await fs.writeFile(
278-
path.join(root, "/src/setup.ts"),
279-
newSetupFileContent,
280-
"utf8"
281-
);
282-
}
227+
if (language === "ts") replaceFiles = tsFilesToRewrite;
283228

284-
spinner.succeed("Template files copied successfully");
229+
// * Apply real values to template files
230+
await Promise.all(
231+
valueReplacer(
232+
replaceFiles,
233+
/___APP NAME___/gm,
234+
applicationName,
235+
authorName
236+
)
237+
);
238+
spinner.succeed("Values in template files replaced successfully");
285239
} catch (error) {
286240
spinner.fail();
287241
throw new Error(error);

src/util.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ export const executeCommand = async (
3131
});
3232
});
3333

34+
/**
35+
* Clean up created directory and files if error occurs.
36+
* @param applicationName Name of application.
37+
*/
3438
export const cleanupError = async (
3539
applicationName: string | undefined
3640
): Promise<void> => {
@@ -47,3 +51,26 @@ export const cleanupError = async (
4751
throw new Error(error);
4852
}
4953
};
54+
55+
/**
56+
* Replaces a token in a list of template files with the appropriate values.
57+
* @param files Array of files to replace values in.
58+
* @param replaceToken Regex used to find the values in the template file.
59+
* @param applicationName Name of application.
60+
* @param authorName Name of author.
61+
*/
62+
export const valueReplacer = (
63+
files: string[],
64+
replaceToken: any,
65+
applicationName: string,
66+
authorName: string
67+
) => {
68+
return files.map(async (filePath: string) => {
69+
const file = await fs.readFile(filePath, "utf-8");
70+
let newFileContent = file.replace(replaceToken, applicationName);
71+
if (filePath === "/src/menu.js" || filePath === "/src/menu.ts")
72+
newFileContent = newFileContent.replace(replaceToken, authorName);
73+
await fs.writeFile(filePath, newFileContent, "utf8");
74+
return;
75+
});
76+
};

0 commit comments

Comments
 (0)