From e48b832e0b72a084d33fa2cbcca332e8209a734f Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Tue, 13 Feb 2024 00:57:45 +0200 Subject: [PATCH] feat: support directory in --config flag --- docs/docs/usage/01-templates.md | 10 ++++- docs/docs/usage/02-configuration_files.md | 47 ++++------------------- src/config.ts | 39 ++++++++++++++++++- src/git.ts | 21 +--------- 4 files changed, 55 insertions(+), 62 deletions(-) diff --git a/docs/docs/usage/01-templates.md b/docs/docs/usage/01-templates.md index 53b861f..abd1112 100644 --- a/docs/docs/usage/01-templates.md +++ b/docs/docs/usage/01-templates.md @@ -109,7 +109,15 @@ Further details: ``` - **The now helper** (for current time) takes the same arguments, minus the first one (`date`) as it - is implicitly the current date. + is implicitly the current date: + + ```typescript + ( + format: string, + offsetAmount?: number, + offsetType?: "years" | "months" | "weeks" | "days" | "hours" | "minutes" | "seconds" + ) + ``` ### Custom Helpers diff --git a/docs/docs/usage/02-configuration_files.md b/docs/docs/usage/02-configuration_files.md index c3e56fa..227d005 100644 --- a/docs/docs/usage/02-configuration_files.md +++ b/docs/docs/usage/02-configuration_files.md @@ -23,48 +23,11 @@ module.exports = { } ``` -The configuration contents are identical to the -[Node.js configuration structure](https://chenasraf.github.io/simple-scaffold/docs/usage/node): - -```ts -interface ScaffoldConfig { - name: string - templates: string[] - output: FileResponse - subdir?: boolean - git?: string - config?: string - key?: string - data?: Record - overwrite?: FileResponse - quiet?: boolean - verbose?: LogLevel - dryRun?: boolean - helpers?: Record - subdirHelper?: DefaultHelpers | string - beforeWrite?( - content: Buffer, - rawContent: Buffer, - outputPath: string, - ): string | Buffer | undefined | Promise -} -``` +For the full configuration options, see [ScaffoldConfigFile](../api/modules#scaffoldconfigfile). If you want to supply functions inside the configurations, you must use a `.js`/`.cjs`/`.mjs` file as JSON does not support non-primitives. -A `.js` file can be just like a `.json` file, make sure to export the final configuration: - -```js -/** @type {import('simple-scaffold').ScaffoldConfigFile} */ -module.exports = { - component: { - templates: ["templates/component"], - output: "src/components", - }, -} -``` - Another feature of using a JS file is you can export a function which will be loaded with the CMD config provided to Simple Scaffold. The `extra` key contains any values not consumed by built-in flags, so you can pre-process your args before outputting a config: @@ -116,7 +79,7 @@ And then: simple-scaffold -c scaffold.json MyComponentName ``` -- When the filename is omitted, the following files will be tried in order: +- When the a directory is given, the following files in the given directory will be tried in order: - `scaffold.config.*` - `scaffold.*` @@ -162,6 +125,12 @@ simple-scaffold -g git://gitlab.com// [-c ] [- simple-scaffold -g https://gitlab.com//.git [-c ] [-k ] ``` +When a config file path is omitted, the files given in the list above will be tried on the root +directory of the git repository. + +**Note:** The repository will be cloned to a temporary directory and removed after the scaffolding +has been done. + ## Use In Node.js You can also start a scaffold from Node.js with a remote file or URL config. diff --git a/src/config.ts b/src/config.ts index 313077f..b9217dc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,5 @@ import path from "node:path" +import fs from "node:fs/promises" import { ConfigLoadConfig, FileResponse, @@ -14,6 +15,7 @@ import { handlebarsParse } from "./parser" import { log } from "./logger" import { resolve, wrapNoopResolver } from "./utils" import { getGitConfig } from "./git" +import { isDir, pathExists } from "./file" /** @internal */ export function getOptionValueForFile( @@ -68,7 +70,7 @@ export async function parseConfigFile(config: ScaffoldCmdConfig, tmpPath: string const configFilename = config.config const configPath = isGit ? config.git : configFilename - log(config, LogLevel.info, `Loading config from ${configFilename} with key ${key}`) + 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 }) @@ -115,8 +117,22 @@ export function githubPartToUrl(part: string): string { export async function getLocalConfig(config: ConfigLoadConfig & Partial): Promise { const { config: configFile, ...logConfig } = config as Required - log(logConfig, LogLevel.info, `Loading config from file ${configFile}`) const absolutePath = path.resolve(process.cwd(), configFile) + + const _isDir = await isDir(absolutePath) + + if (_isDir) { + log(logConfig, LogLevel.debug, `Resolving config file from directory ${absolutePath}`) + const file = await findConfigFile(absolutePath) + const exists = await pathExists(file) + if (!exists) { + throw new Error(`Could not find config file in directory ${absolutePath}`) + } + log(logConfig, LogLevel.info, `Loading config from: ${path.resolve(absolutePath, file)}`) + return wrapNoopResolver(import(path.resolve(absolutePath, file))) + } + + log(logConfig, LogLevel.info, `Loading config from: ${absolutePath}`) return wrapNoopResolver(import(absolutePath)) } @@ -138,3 +154,22 @@ export async function getRemoteConfig( return getGitConfig(url, configFile, tmpPath, logConfig) } + +/** @internal */ +export async function findConfigFile(root: string): Promise { + const allowed = ["mjs", "cjs", "js", "json"].reduce((acc, ext) => { + acc.push(`scaffold.config.${ext}`) + acc.push(`scaffold.${ext}`) + return acc + }, [] as string[]) + for (const file of allowed) { + const exists = await fs + .stat(path.resolve(root, file)) + .then(() => true) + .catch(() => false) + if (exists) { + return file + } + } + throw new Error(`Could not find config file in git repo`) +} diff --git a/src/git.ts b/src/git.ts index 77c8d14..51a444c 100644 --- a/src/git.ts +++ b/src/git.ts @@ -1,9 +1,9 @@ import path from "node:path" -import fs from "node:fs/promises" import { log } from "./logger" import { AsyncResolver, LogConfig, LogLevel, ScaffoldCmdConfig, ScaffoldConfigMap } from "./types" import { spawn } from "node:child_process" import { resolve, wrapNoopResolver } from "./utils" +import { findConfigFile } from "./config" export async function getGitConfig( url: URL, @@ -60,22 +60,3 @@ export async function loadGitConfig({ } return wrapNoopResolver(fixedConfig) } - -/** @internal */ -export async function findConfigFile(root: string): Promise { - const allowed = ["mjs", "cjs", "js", "json"].reduce((acc, ext) => { - acc.push(`scaffold.config.${ext}`) - acc.push(`scaffold.${ext}`) - return acc - }, [] as string[]) - for (const file of allowed) { - const exists = await fs - .stat(path.resolve(root, file)) - .then(() => true) - .catch(() => false) - if (exists) { - return file - } - } - throw new Error(`Could not find config file in git repo`) -}