1
0
Fork 0

refactor(new-design): Make some changes to lib/utils.js

* Support `.mustache` template files in `packages/new-design/shared/`, just as in `packages/new-design/templates/*/`.
* Only render files with an explicit `.mustache` suffix.
* In `downloadLabFiles`:
  * Don't try to write response failures into the destination file. This was failing because it wasn't wrapping the error in `{data: ...}` to imitate a successful axios response.
  * Actually wait for `writeFile` to finish. Don't try to add to `promises` after they've already been collected with `Promise.all`.
* General refactoring (really leaning into Promises here...)
This commit is contained in:
Nikhil Chelliah 2022-10-14 17:37:52 -04:00
parent c959858e6c
commit 332541bac5

View file

@ -1,6 +1,6 @@
import { config } from './config.mjs' import { config } from './config.mjs'
import { mkdir, readFile, writeFile, copyFile } from 'node:fs/promises' import { mkdir, readFile, writeFile, copyFile } from 'node:fs/promises'
import { join, dirname } from 'path' import { join, dirname, relative } from 'path'
import mustache from 'mustache' import mustache from 'mustache'
import rdir from 'recursive-readdir' import rdir from 'recursive-readdir'
import chalk from 'chalk' import chalk from 'chalk'
@ -11,12 +11,13 @@ import axios from 'axios'
import { fileURLToPath } from 'url' import { fileURLToPath } from 'url'
// Current working directory // Current working directory
let cwd let filename
try { try {
cwd = __dirname filename = __filename
} catch { } catch {
cwd = dirname(fileURLToPath(import.meta.url)) filename = fileURLToPath(import.meta.url)
} }
const newDesignDir = join(filename, '../..')
const nl = '\n' const nl = '\n'
const tab = ' ' const tab = ' '
@ -114,41 +115,49 @@ export const getChoices = async () => {
} }
// Keep track of directories that need to be created // Keep track of directories that need to be created
const dirs = {} const dirPromises = {}
const ensureDir = async (file, suppress = false) => { const ensureDir = async (file, suppress = false) => {
const dir = suppress ? dirname(file.replace(suppress)) : dirname(file) const dir = suppress ? dirname(file.replace(suppress)) : dirname(file)
if (!dirs[dir]) { if (!dirPromises[dir]) {
await mkdir(dir, { recursive: true }) dirPromises[dir] = mkdir(dir, { recursive: true })
dirs[dir] = true }
await dirPromises[dir]
}
// Helper method to copy template files
const copyFileOrTemplate = async (fromRoot, toRoot, relativeFile, templateVars) => {
const from = join(fromRoot, relativeFile)
const to = join(
toRoot,
relativeFile.endsWith('.mustache') ? relativeFile.slice(0, -9) : relativeFile
)
await ensureDir(to)
if (relativeFile.endsWith('.mustache')) {
const template = await readFile(from, 'utf-8')
const rendered = mustache.render(template, templateVars)
await writeFile(to, rendered)
} else {
await copyFile(from, to)
} }
} }
// Helper method to copy template files // Helper method to copy template files
const copyTemplate = async (config, choices) => { const copyAll = async (config, templateVars) => {
// Copy files in parallel rather than using await
const promises = []
// Copy shared files // Copy shared files
for (const from of config.files.shared) { await Promise.all(
// FIXME: Explain the -7 config.relativeFiles.shared.map((from) => {
const to = join(config.dest, from.slice(config.source.shared.length - 7)) copyFileOrTemplate(config.source.shared, config.dest, from, templateVars)
if (!dirs[to]) await ensureDir(to) })
promises.push(copyFile(from, to)) )
}
// Template files // Template files
for (const from of config.files.template) { await Promise.all(
let to = join(config.dest, from.slice(config.source.template.length - 7)) config.relativeFiles.template.map((from) => {
if (to.slice(-9) === '.mustache') to = to.slice(0, -9) copyFileOrTemplate(config.source.template, config.dest, from, templateVars)
if (!dirs[to]) await ensureDir(to) })
// Template out file )
const src = await readFile(from, 'utf-8')
promises.push(writeFile(to, mustache.render(src, { name: choices.name, tag: config.tag })))
}
await Promise.all(promises)
return
} }
// Helper method to run [yarn|npm] install // Helper method to run [yarn|npm] install
@ -162,25 +171,25 @@ const installDependencies = async (config, choices) =>
const downloadLabFiles = async (config) => { const downloadLabFiles = async (config) => {
const promises = [] const promises = []
for (const dir in config.fetch) { for (const dir in config.fetch) {
for (const file of config.fetch[dir]) { promises.push(
const to = typeof file === 'string' ? join(config.dest, file) : join(config.dest, file.to) ...config.fetch[dir].map(async (file) => {
if (!dirs[to]) await ensureDir(to) const to = typeof file === 'string' ? join(config.dest, file) : join(config.dest, file.to)
promises.push( await ensureDir(to)
axios try {
.get( const res = await axios.get(
`${config.fileUri}/${config.repo}/${config.branch}/${dir}/${ `${config.fileUri}/${config.repo}/${config.branch}/${dir}/${
typeof file === 'string' ? file : file.from typeof file === 'string' ? file : file.from
}` }`
) )
.catch((err) => console.log(err)) await writeFile(to, res.data)
.then((res) => promises.push(writeFile(to, res.data))) } catch (err) {
) console.log(err)
} }
})
)
} }
await Promise.all(promises) return Promise.all(promises)
return
} }
// Helper method to initialize a git repository // Helper method to initialize a git repository
@ -253,21 +262,21 @@ const showTips = (config, choices) => {
// Creates the environment based on the user's choices // Creates the environment based on the user's choices
export const createEnvironment = async (choices) => { export const createEnvironment = async (choices) => {
// Store directories for re-use // Store directories for re-use
;(config.cwd = cwd), config.source = {
(config.source = { template: `${newDesignDir}/templates/from-${choices.template}`,
root: cwd, shared: `${newDesignDir}/shared`,
template: cwd + `/../templates/from-${choices.template}`, }
shared: cwd + `/../shared`,
})
config.dest = join(process.cwd(), choices.name) config.dest = join(process.cwd(), choices.name)
// Create target directory // Create target directory
await mkdir(config.dest, { recursive: true }) await mkdir(config.dest, { recursive: true })
// Find files // Find files
config.files = { config.relativeFiles = {
template: await rdir(config.source.template), template: (await rdir(config.source.template)).map((file) =>
shared: await rdir(config.source.shared), relative(config.source.template, file)
),
shared: (await rdir(config.source.shared)).map((file) => relative(config.source.shared, file)),
} }
// Output a linebreak // Output a linebreak
@ -275,7 +284,12 @@ export const createEnvironment = async (choices) => {
// Copy/Template files // Copy/Template files
try { try {
await oraPromise(copyTemplate(config, choices), { const templateVars = {
template: choices.template,
name: choices.name,
tag: config.tag,
}
await oraPromise(copyAll(config, templateVars), {
text: text:
chalk.white.bold('🟨⬜⬜⬜ Copying template files') + chalk.white.bold('🟨⬜⬜⬜ Copying template files') +
chalk.white.dim(' | Just a moment'), chalk.white.dim(' | Just a moment'),