Compare commits

...

4 Commits

Author SHA1 Message Date
semantic-release-bot
df6c351cb0 chore(release): 2.2.0 [skip ci]
# [2.2.0](https://github.com/chenasraf/simple-scaffold/compare/v2.1.0...v2.2.0) (2024-02-23)

### Features

* `list` command ([d579c09](d579c09c11))
* add `--before-write` cli option ([#89](https://github.com/chenasraf/simple-scaffold/issues/89)) ([5f810e2](5f810e2116))
2024-02-23 22:42:32 +00:00
Chen Asraf
5f810e2116 feat: add --before-write cli option (#89)
* feat: add `--before-write` cli option

* refactor: cleanup before write wrapper

* docs: add before-write docs
2024-02-24 00:41:56 +02:00
d579c09c11 feat: list command 2024-02-24 00:41:56 +02:00
3765398ab9 ci: attemp to fix pack cmd 2024-02-24 00:41:56 +02:00
12 changed files with 308 additions and 89 deletions

View File

@@ -1,5 +1,13 @@
# Change Log
# [2.2.0](https://github.com/chenasraf/simple-scaffold/compare/v2.1.0...v2.2.0) (2024-02-23)
### Features
* `list` command ([d579c09](https://github.com/chenasraf/simple-scaffold/commit/d579c09c11f2149fe7bb4515297c1287fa67083e))
* add `--before-write` cli option ([#89](https://github.com/chenasraf/simple-scaffold/issues/89)) ([5f810e2](https://github.com/chenasraf/simple-scaffold/commit/5f810e21160816bc683cc0f375de318ff874871c))
# [2.1.0](https://github.com/chenasraf/simple-scaffold/compare/v2.0.2...v2.1.0) (2024-02-12)

View File

@@ -11,24 +11,57 @@ Usage: simple-scaffold [options]
To see this and more information anytime, add the `-h` or `--help` flag to your call, e.g.
`npx simple-scaffold@latest -h`.
| Command \| alias | |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name` \| `-n` | Name to be passed to the generated files. `{{name}}` and other data parameters inside contents and file names will be replaced accordingly. You may omit the `--name` or `-n` for this specific option. |
| `--config`\|`-c` | Filename to load config from instead of passing arguments to CLI or using a Node.js script. See examples for syntax. This can also work in conjunction with `--git` or `--github` to point to remote files, and with `--key` to denote which key to select from the file., |
| `--git`\|`-g` | Git URL to load config from instead of passing arguments to CLI or using a Node.js script. See examples for syntax. |
| `--key` \| `-k` | Key to load inside the config file. This overwrites the config key provided after the colon in `--config` (e.g. `--config scaffold.cmd.js:component`) |
| `--output` \| `-o` | Path to output to. If `--create-sub-folder` is enabled, the subfolder will be created inside this path. Default is current working directory. |
| `--templates` \| `-t` | Template files to use as input. You may provide multiple files, each of which can be a relative or absolute path, or a glob pattern for multiple file matching easily. |
| `--overwrite` \| `-w` | Enable to override output files, even if they already exist. |
| `--data` \| `-d` | Add custom data to the templates. By default, only your app name is included. |
| `--append-data` \| `-D` | Append additional custom data to the templates, which will overwrite `--data`, using an alternate syntax, which is easier to use with CLI: `-D key1=string -D key2:=raw` |
| `--create-sub-folder` \| `-s` | Create subfolder with the input name |
| `--sub-folder-name-helper` \| `-sh` | Default helper to apply to subfolder name when using `--create-sub-folder true`. |
| `--quiet` \| `-q` | Suppress output logs (Same as `--log-level none`) |
| `--log-level` \| `-l` | Determine amount of logs to display. The values are: `none \| debug \| info \| warn \| error`. The provided level will display messages of the same level or higher. |
| `--dry-run` \| `-dr` | Don't emit files. This is good for testing your scaffolds and making sure they don't fail, without having to write actual file contents or create directories. |
| `--help` \| `-h` | Show this help message |
| `--version` \| `-v` | Display version. |
| Command \| alias | |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name` \| `-n` | Name to be passed to the generated files. `{{name}}` and other data parameters inside contents and file names will be replaced accordingly. You may omit the `--name` or `-n` for this specific option. |
| `--config`\|`-c` | Filename or directory to load config from |
| `--git`\|`-g` | Git URL or GitHub path to load a template from. |
| `--key` \| `-k` | Key to load inside the config file. This overwrites the config key provided after the colon in `--config` (e.g. `--config scaffold.cmd.js:component`) |
| `--output` \| `-o` | Path to output to. If `--create-sub-folder` is enabled, the subfolder will be created inside this path. Default is current working directory. |
| `--templates` \| `-t` | Template files to use as input. You may provide multiple files, each of which can be a relative or absolute path, or a glob pattern for multiple file matching easily. |
| `--overwrite` \| `-w` | Enable to override output files, even if they already exist. |
| `--data` \| `-d` | Add custom data to the templates. By default, only your app name is included. |
| `--append-data` \| `-D` | Append additional custom data to the templates, which will overwrite `--data`, using an alternate syntax, which is easier to use with CLI: `-D key1=string -D key2:=raw` |
| `--create-sub-folder` \| `-s` | Create subfolder with the input name |
| `--sub-folder-name-helper` \| `-sh` | Default helper to apply to subfolder name when using `--create-sub-folder true`. |
| `--quiet` \| `-q` | Suppress output logs (Same as `--log-level none`) |
| `--log-level` \| `-l` | Determine amount of logs to display. The values are: `none \| debug \| info \| warn \| error`. The provided level will display messages of the same level or higher. |
| `--before-write` \| `-B` | Run a script before writing the files. This can be a command or a path to a file. A temporary file path will be passed to the given command and the command should return a string for the final output. |
| `--dry-run` \| `-dr` | Don't emit files. This is good for testing your scaffolds and making sure they don't fail, without having to write actual file contents or create directories. |
| `--help` \| `-h` | Show this help message |
| `--version` \| `-v` | Display version. |
### Before Write option
This option allows you to preprocess a file before it is being written, such as running a formatter,
linter or other commands.
To use this option, pass it the command you would like to run. The following tokens will be replaced
in your string:
- `{{path}}` - the temporary file path for you to read from
- `{{rawpath}}` - a different file path containing the raw file contents **before** they were
handled by Handlebars.js.
If none of these tokens are found, the regular (non-raw) path will be appended to the end of the
command.
```shell
simple-scaffold -c . --before-write prettier
# command: prettier /tmp/somefile
simple-scaffold -c . --before-write 'cat {{path}} | my-linter'
# command: cat /tmp/somefile | my-linter
```
The command should return the string to write to the file through standard output (stdout), and not
re-write the tmp file as it is not used for writing. Returning an empty string (after trimming) will
discard the result and write the original file contents.
See
[beforeWrite](https://chenasraf.github.io/simple-scaffold/docs/api/interfaces/ScaffoldConfig#beforewrite)
Node.js API for more details. Instead of returning `undefined` to keep the default behavior, you can
output `''` for the same effect.
## Examples:

View File

@@ -2,6 +2,8 @@
title: Node.js Usage
---
## Overview
You can build the scaffold yourself, if you want to create more complex arguments, scaffold groups,
etc - simply pass a config object to the Scaffold function when you are ready to start.
@@ -33,6 +35,19 @@ interface ScaffoldConfig {
}
```
### Before Write option
This option allows you to preprocess a file before it is being written, such as running a formatter,
linter or other commands.
To use this option, you can run any async/blocking command, and return a string as the final output
to be used as the file contents.
Returning `undefined` will keep the file contents as-is, after normal Handlebars.js procesing by
Simple Scaffold.
## Example
This is an example of loading a complete scaffold via Node.js:
```typescript
@@ -50,6 +65,8 @@ const config = {
helpers: {
twice: (text) => [text, text].join(" ")
},
// return a string to replace the final file contents after pre-processing, or `undefined`
// to keep it as-is
beforeWrite: (content, rawContent, outputPath) => content.toString().toUpperCase()
}

View File

@@ -1,7 +1,7 @@
import * as React from "react"
import * as css from "./{{pascalCae name}}.css"
import * as css from "./{{pascalCase name}}.css"
class {{pascalCae name}} extends React.Component<any> {
class {{pascalCase name}} extends React.Component<any> {
private {{ property }}
constructor(props: any) {
@@ -10,8 +10,8 @@ class {{pascalCae name}} extends React.Component<any> {
}
public render() {
return <div className={ css.{{pascalCae name}} } />
return <div className={ css.{{pascalCase name}} } />
}
}
export default {pascalCae nName}}
export default {{pascalCase name}}

View File

@@ -1,6 +1,6 @@
{
"name": "simple-scaffold",
"version": "2.1.0",
"version": "2.2.0",
"description": "Generate any file structure - from single components to entire app boilerplates, with a single command.",
"homepage": "https: //chenasraf.github.io/simple-scaffold",
"repository": {

View File

@@ -13,31 +13,27 @@ module.exports = {
"@semantic-release/npm",
{
// only update the pkg version on root, don't publish
// this is to keep package.json version in sync with the release
npmPublish: false,
},
],
// [
// '@semantic-release/npm',
// {
// // only update the pkg version on doc, don't publish
// npmPublish: false,
// pkgRoot: 'doc',
// },
// ]
[
"@semantic-release/exec",
{
publish: "cd ./dist && pnpm pack --pack-destination=../",
// pack the dist folder, during publish step (after version was bumped)
publishCmd: 'echo "Packing..."; cd ./dist && pnpm pack --pack-destination=../; echo "Done"',
},
],
[
"@semantic-release/npm",
{
// publish from dist dir instead of root
// this is the actual uild output
pkgRoot: "dist",
},
],
[
// Release to GitHub
"@semantic-release/github",
{
assets: ["*.tgz"],
@@ -45,14 +41,16 @@ module.exports = {
],
branch === "master"
? [
"@semantic-release/changelog",
{
changelogFile: "CHANGELOG.md",
changelogTitle: "# Change Log",
},
]
// Update CHANGELOG.md only on master
"@semantic-release/changelog",
{
changelogFile: "CHANGELOG.md",
changelogTitle: "# Change Log",
},
]
: undefined,
[
// Commit the package.json and CHANGELOG.md files to git (if modified)
"@semantic-release/git",
{
assets: ["package.json", "CHANGELOG.md"].filter(Boolean),

View File

@@ -1,22 +1,24 @@
#!/usr/bin/env node
import os from "node:os"
import { massarg } from "massarg"
import chalk from "chalk"
import { LogLevel, ScaffoldCmdConfig } from "./types"
import { Scaffold } from "./scaffold"
import path from "node:path"
import fs from "node:fs/promises"
import { parseAppendData, parseConfigFile } from "./config"
import { massarg } from "massarg"
import chalk from "chalk"
import { ListCommandCliOptions, LogLevel, ScaffoldCmdConfig } from "./types"
import { Scaffold } from "./scaffold"
import { getConfigFile, parseAppendData, parseConfigFile } from "./config"
import { log } from "./logger"
import { MassargCommand } from "massarg/command"
import { getUniqueTmpPath as generateUniqueTmpPath } from "./file"
export async function parseCliArgs(args = process.argv.slice(2)) {
const isProjectRoot = Boolean(await fs.stat(path.join(__dirname, "package.json")).catch(() => false))
const pkgFile = await fs.readFile(path.resolve(__dirname, isProjectRoot ? "." : "..", "package.json"))
const pkg = JSON.parse(pkgFile.toString())
const isVersionFlag = args.includes("--version") || args.includes("-v")
const isConfigProvided =
args.includes("--config") || args.includes("-c") || args.includes("--git") || args.includes("-g") || isVersionFlag
const isConfigFileProvided = args.includes("--config") || args.includes("-c")
const isGitProvided = args.includes("--git") || args.includes("-g")
const isConfigProvided = isConfigFileProvided || isGitProvided || isVersionFlag
return massarg<ScaffoldCmdConfig>({
name: pkg.name,
@@ -28,7 +30,7 @@ export async function parseCliArgs(args = process.argv.slice(2)) {
return
}
log(config, LogLevel.info, `Simple Scaffold v${pkg.version}`)
const tmpPath = path.resolve(os.tmpdir(), `scaffold-config-${Date.now()}`)
const tmpPath = generateUniqueTmpPath()
try {
log(config, LogLevel.debug, "Parsing config file...", config)
const parsed = await parseConfigFile(config, tmpPath)
@@ -46,24 +48,20 @@ export async function parseCliArgs(args = process.argv.slice(2)) {
aliases: ["n"],
description:
"Name to be passed to the generated files. `{{name}}` and other data parameters inside " +
"contents and file names will be replaced accordingly. You may omit the `--name` or `-n` for this specific option.",
"contents and file names will be replaced accordingly. You may omit the `--name` or `-n` " +
"for this specific option.",
isDefault: true,
required: !isConfigProvided,
})
.option({
name: "config",
aliases: ["c"],
description:
"Filename to load config from instead of passing arguments to CLI or using a Node.js " +
"script. See examples for syntax. This can also work in conjunction with `--git` or `--github` to point " +
"to remote files, and with `--key` to denote which key to select from the file.",
description: "Filename or directory to load config from",
})
.option({
name: "git",
aliases: ["g"],
description:
"Git URL to load config from instead of passing arguments to CLI or using a Node.js script. See " +
"examples for syntax.",
description: "Git URL or GitHub path to load a template from.",
})
.option({
name: "key",
@@ -146,6 +144,14 @@ export async function parseCliArgs(args = process.argv.slice(2)) {
return val
},
})
.option({
name: "before-write",
aliases: ["B"],
description:
"Run a script before writing the files. This can be a command or a path to a" +
" file. A temporary file path will be passed to the given command and the command should " +
"return a string for the final output.",
})
.flag({
name: "dry-run",
aliases: ["dr"],
@@ -159,6 +165,67 @@ export async function parseCliArgs(args = process.argv.slice(2)) {
aliases: ["v"],
description: "Display version.",
})
.command(
new MassargCommand<ListCommandCliOptions>({
name: "list",
aliases: ["ls"],
description: "List all available templates for a given config. See `list -h` for more information.",
run: async (_config) => {
const tmpPath = generateUniqueTmpPath()
const config = {
templates: [],
name: "",
version: false,
output: "",
subdir: false,
overwrite: false,
dryRun: false,
..._config,
config: _config.config ?? (!_config.git ? process.cwd() : undefined),
}
try {
const file = await getConfigFile(config, tmpPath)
console.log(chalk.underline`Available templates:\n`)
console.log(Object.keys(file).join("\n"))
} catch (e) {
const message = "message" in (e as any) ? (e as any).message : e?.toString()
log(config, LogLevel.error, message)
} finally {
log(config, LogLevel.debug, "Cleaning up temporary files...", tmpPath)
await fs.rm(tmpPath, { recursive: true, force: true })
}
},
})
.option({
name: "config",
aliases: ["c"],
description: "Filename or directory to load config from. Defaults to current working directory.",
})
.option({
name: "git",
aliases: ["g"],
description: "Git URL or GitHub path to load a template from.",
})
.option({
name: "log-level",
aliases: ["l"],
defaultValue: LogLevel.none,
description:
"Determine amount of logs to display. The values are: " +
`${chalk.bold`\`none | debug | info | warn | error\``}. ` +
"The provided level will display messages of the same level or higher.",
parse: (v) => {
const val = v.toLowerCase()
if (!(val in LogLevel)) {
throw new Error(`Invalid log level: ${val}, must be one of: ${Object.keys(LogLevel).join(", ")}`)
}
return val
},
})
.help({
bindOption: true,
}),
)
.example({
description: "Usage with config file",
input: "simple-scaffold -c scaffold.cmd.js --key component",

View File

@@ -10,12 +10,14 @@ import {
ScaffoldCmdConfig,
ScaffoldConfig,
ScaffoldConfigFile,
ScaffoldConfigMap,
} from "./types"
import { handlebarsParse } from "./parser"
import { log } from "./logger"
import { resolve, wrapNoopResolver } from "./utils"
import { getGitConfig } from "./git"
import { isDir, pathExists } from "./file"
import { createDirIfNotExists, getUniqueTmpPath, isDir, pathExists } from "./file"
import { exec, spawn } from "node:child_process"
/** @internal */
export function getOptionValueForFile<T>(
@@ -50,43 +52,49 @@ function isWrappedWithQuotes(string: string): boolean {
}
/** @internal */
export async function parseConfigFile(config: ScaffoldCmdConfig, tmpPath: string): Promise<ScaffoldConfig> {
let output: ScaffoldConfig = config
if (config.quiet) {
config.logLevel = LogLevel.none
}
export async function getConfigFile(config: ScaffoldCmdConfig, tmpPath: string): Promise<ScaffoldConfigMap> {
if (config.git && !config.git.includes("://")) {
log(config, LogLevel.info, `Loading config from GitHub ${config.git}`)
config.git = githubPartToUrl(config.git)
}
const shouldLoadConfig = config.config || config.git
const isGit = Boolean(config.git)
const configFilename = config.config
const configPath = isGit ? config.git : configFilename
log(config, LogLevel.info, `Loading config from file ${configFilename}`)
const configPromise = await (isGit
? getRemoteConfig({ git: configPath, config: configFilename, logLevel: config.logLevel, tmpPath })
: getLocalConfig({ config: configFilename, logLevel: config.logLevel }))
// resolve the config
let configImport = await resolve(configPromise, config)
// If the config is a function or promise, return the output
if (typeof configImport.default === "function" || configImport.default instanceof Promise) {
log(config, LogLevel.debug, "Config is a function or promise, resolving...")
configImport = await resolve(configImport.default, config)
}
return configImport
}
/** @internal */
export async function parseConfigFile(config: ScaffoldCmdConfig, tmpPath: string): Promise<ScaffoldConfig> {
let output: ScaffoldConfig = { ...config, beforeWrite: undefined }
if (config.quiet) {
config.logLevel = LogLevel.none
}
const shouldLoadConfig = Boolean(config.config || config.git)
if (shouldLoadConfig) {
const isGit = Boolean(config.git)
const key = config.key ?? "default"
const configFilename = config.config
const configPath = isGit ? config.git : configFilename
log(config, LogLevel.info, `Loading config from file ${configFilename} with key ${key}`)
const configPromise = await (isGit
? getRemoteConfig({ git: configPath, config: configFilename, logLevel: config.logLevel, tmpPath })
: getLocalConfig({ config: configFilename, logLevel: config.logLevel }))
// resolve the config
let configImport = await resolve(configPromise, config)
// If the config is a function or promise, return the output
if (typeof configImport.default === "function" || configImport.default instanceof Promise) {
log(config, LogLevel.debug, "Config is a function or promise, resolving...")
configImport = await resolve(configImport.default, config)
}
const configImport = await getConfigFile(config, tmpPath)
if (!configImport[key]) {
throw new Error(`Template "${key}" not found in ${configFilename}`)
throw new Error(`Template "${key}" not found in ${config.config}`)
}
const imported = configImport[key]
@@ -94,6 +102,7 @@ export async function parseConfigFile(config: ScaffoldCmdConfig, tmpPath: string
output = {
...config,
...imported,
beforeWrite: undefined,
data: {
...(imported as any).data,
...config.data,
@@ -102,9 +111,12 @@ export async function parseConfigFile(config: ScaffoldCmdConfig, tmpPath: string
}
output.data = { ...output.data, ...config.appendData }
output.beforeWrite = config.beforeWrite ? wrapBeforeWrite(config, config.beforeWrite) : undefined
if (!output.name) {
throw new Error("simple-scaffold: Missing required option: name")
}
log(output, LogLevel.debug, "Parsed config", output)
return output
}
@@ -175,3 +187,72 @@ export async function findConfigFile(root: string): Promise<string> {
}
throw new Error(`Could not find config file in git repo`)
}
function wrapBeforeWrite(
config: LogConfig & Pick<ScaffoldConfig, "dryRun">,
beforeWrite: string,
): ScaffoldConfig["beforeWrite"] {
return async (content, rawContent, outputFile) => {
const tmpPath = path.join(getUniqueTmpPath(), path.basename(outputFile))
await createDirIfNotExists(path.dirname(tmpPath), config)
const ext = path.extname(outputFile)
const rawTmpPath = tmpPath.replace(ext, ".raw" + ext)
try {
log(config, LogLevel.debug, "Parsing beforeWrite command", beforeWrite)
let cmd = await prepareBeforeWriteCmd({ beforeWrite, tmpPath, content, rawTmpPath, rawContent })
const result = await new Promise<string | undefined>((resolve, reject) => {
log(config, LogLevel.debug, "Running parsed beforeWrite command:", cmd)
const proc = exec(cmd)
proc.stdout!.on("data", (data) => {
if (data.trim()) {
resolve(data.toString())
} else {
resolve(undefined)
}
})
proc.stderr!.on("data", (data) => {
reject(data.toString())
})
})
return result
} catch (e) {
log(config, LogLevel.debug, e)
log(config, LogLevel.warning, "Error running beforeWrite command, returning original content")
return undefined
} finally {
await fs.rm(tmpPath, { force: true })
await fs.rm(rawTmpPath, { force: true })
}
}
}
async function prepareBeforeWriteCmd({
beforeWrite,
tmpPath,
content,
rawTmpPath,
rawContent,
}: {
beforeWrite: string
tmpPath: string
content: Buffer
rawTmpPath: string
rawContent: Buffer
}): Promise<string> {
let cmd: string = ""
const pathReg = /\{\{\s*path\s*\}\}/gi
const rawPathReg = /\{\{\s*rawpath\s*\}\}/gi
if (pathReg.test(beforeWrite)) {
await fs.writeFile(tmpPath, content)
cmd = beforeWrite.replaceAll(pathReg, tmpPath)
}
if (rawPathReg.test(beforeWrite)) {
await fs.writeFile(rawTmpPath, rawContent)
cmd = beforeWrite.replaceAll(rawPathReg, rawTmpPath)
}
if (!cmd) {
await fs.writeFile(tmpPath, content)
cmd = [beforeWrite, tmpPath].join(" ")
}
return cmd
}

View File

@@ -1,7 +1,8 @@
import os from "node:os"
import path from "node:path"
import { F_OK } from "node:constants"
import { LogLevel, ScaffoldConfig } from "./types"
import fs from "node:fs/promises"
import { F_OK } from "node:constants"
import { LogConfig, LogLevel, ScaffoldConfig } from "./types"
import { glob, hasMagic } from "glob"
import { log } from "./logger"
import { getOptionValueForFile } from "./config"
@@ -10,7 +11,10 @@ import { handleErr } from "./utils"
const { stat, access, mkdir, readFile, writeFile } = fs
export async function createDirIfNotExists(dir: string, config: ScaffoldConfig): Promise<void> {
export async function createDirIfNotExists(
dir: string,
config: LogConfig & Pick<ScaffoldConfig, "dryRun">,
): Promise<void> {
if (config.dryRun) {
log(config, LogLevel.info, `Dry Run. Not creating dir ${dir}`)
return
@@ -142,6 +146,7 @@ export async function copyFileTransformed(
if (exists && overwrite) {
log(config, LogLevel.info, `File ${outputPath} exists, overwriting`)
}
log(config, LogLevel.debug, `Processing file ${inputPath}`)
const templateBuffer = await readFile(inputPath)
const unprocessedOutputContents = handlebarsParse(config, templateBuffer)
const finalOutputContents =
@@ -149,7 +154,6 @@ export async function copyFileTransformed(
if (!config.dryRun) {
await writeFile(outputPath, finalOutputContents)
log(config, LogLevel.info, "Done.")
} else {
log(config, LogLevel.info, "Dry Run. Output should be:")
log(config, LogLevel.info, finalOutputContents.toString())
@@ -157,6 +161,7 @@ export async function copyFileTransformed(
} else if (exists) {
log(config, LogLevel.info, `File ${outputPath} already exists, skipping`)
}
log(config, LogLevel.info, "Done.")
}
export function getOutputDir(config: ScaffoldConfig, outputPathOpt: string, basePath: string): string {
@@ -209,3 +214,8 @@ export async function handleTemplateFile(
}
})
}
/** @internal */
export function getUniqueTmpPath(): string {
return path.resolve(os.tmpdir(), `scaffold-config-${Date.now()}-${Math.random().toString(36).slice(2)}`)
}

View File

@@ -1,3 +1,4 @@
import util from "util"
import { LogConfig, LogLevel, ScaffoldConfig } from "./types"
import chalk from "chalk"
@@ -30,7 +31,7 @@ export function log(config: LogConfig, level: LogLevel, ...obj: any[]): void {
i instanceof Error
? chalkFn(i, JSON.stringify(i, undefined, 1), i.stack)
: typeof i === "object"
? chalkFn(JSON.stringify(i, undefined, 1))
? util.inspect(i, { depth: null, colors: true })
: chalkFn(i),
),
)

View File

@@ -121,7 +121,7 @@ export function handlebarsParse(
return Buffer.from(outputContents)
} catch (e) {
log(config, LogLevel.debug, e)
log(config, LogLevel.info, "Couldn't parse file with handlebars, returning original content")
log(config, LogLevel.warning, "Couldn't parse file with handlebars, returning original content")
return Buffer.from(templateBuffer)
}
}

View File

@@ -368,6 +368,8 @@ export type ScaffoldCmdConfig = {
git?: string
/** Display version */
version: boolean
/** Run a script before writing the files. This can be a command or a path to a file. The file contents will be passed to the given command. */
beforeWrite?: string
}
/**
@@ -413,3 +415,5 @@ export type RemoteConfigLoadConfig = LogConfig & Pick<ScaffoldCmdConfig, "config
/** @internal */
export type MinimalConfig = Pick<ScaffoldCmdConfig, "name" | "key">
export type ListCommandCliOptions = Pick<ScaffoldCmdConfig, "config" | "git" | "logLevel" | "quiet">